Skip to content

Commit

Permalink
fix named pipe pivots
Browse files Browse the repository at this point in the history
  • Loading branch information
moloch-- committed Jan 22, 2022
1 parent bcc7fb0 commit b5d1e9a
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 79 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Sliver is an open source cross-platform adversary emulation/red team framework,

The server and client support MacOS, Windows, and Linux. Implants are supported on MacOS, Windows, and Linux (and possibly every Golang compiler target but we've not tested them all).

![Go](https://github.com/BishopFox/sliver/workflows/Go/badge.svg?branch=master) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
![Go](https://github.com/BishopFox/sliver/workflows/Go/badge.svg?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/BishopFox/sliver)](https://goreportcard.com/report/github.com/BishopFox/sliver) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

### Features

Expand Down
21 changes: 15 additions & 6 deletions client/command/armory/parsers.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ type ArmoryPackageParser func(*ArmoryPackage, bool, ArmoryHTTPConfig) (*minisign

var (
indexParsers = map[string]ArmoryIndexParser{
"api.github.com": GithubArmoryIndexParser,
"api.github.com": GithubAPIArmoryIndexParser,
}
pkgParsers = map[string]ArmoryPackageParser{
"api.github.com": GithubArmoryPackageParser,
"api.github.com": GithubAPIArmoryPackageParser,
}
)

Expand All @@ -63,6 +63,10 @@ type armoryPkgResponse struct {
TarGzURL string `json:"tar_gz_url"`
}

//
// Default Parsers for Self-Hosted Armories
//

// DefaultArmoryParser - Parse the armory index directly from the url
func DefaultArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) (*ArmoryIndex, error) {
var publicKey minisign.PublicKey
Expand Down Expand Up @@ -163,6 +167,10 @@ func DefaultArmoryPkgParser(armoryPkg *ArmoryPackage, sigOnly bool, clientConfig
return sig, tarGz, nil
}

//
// GitHub API Parsers
//

type GithubAsset struct {
ID int `json:"id"`
Name string `json:"name"`
Expand All @@ -187,8 +195,8 @@ type GithubRelease struct {
Assets []GithubAsset `json:"assets"`
}

// GithubArmoryIndexParser - Parse the armory index from a GitHub release
func GithubArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) (*ArmoryIndex, error) {
// GithubAPIArmoryIndexParser - Parse the armory index from a GitHub release
func GithubAPIArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig ArmoryHTTPConfig) (*ArmoryIndex, error) {
var publicKey minisign.PublicKey
err := publicKey.UnmarshalText([]byte(armoryConfig.PublicKey))
if err != nil {
Expand Down Expand Up @@ -263,8 +271,8 @@ func GithubArmoryIndexParser(armoryConfig *assets.ArmoryConfig, clientConfig Arm
return armoryIndex, nil
}

// GithubArmoryPackageParser - Retrieve the minisig and tar.gz for an armory package from a GitHub release
func GithubArmoryPackageParser(armoryPkg *ArmoryPackage, sigOnly bool, clientConfig ArmoryHTTPConfig) (*minisign.Signature, []byte, error) {
// GithubAPIArmoryPackageParser - Retrieve the minisig and tar.gz for an armory package from a GitHub release
func GithubAPIArmoryPackageParser(armoryPkg *ArmoryPackage, sigOnly bool, clientConfig ArmoryHTTPConfig) (*minisign.Signature, []byte, error) {
var publicKey minisign.PublicKey
err := publicKey.UnmarshalText([]byte(armoryPkg.PublicKey))
if err != nil {
Expand Down Expand Up @@ -350,6 +358,7 @@ func httpClient(config ArmoryHTTPConfig) *http.Client {
Dial: (&net.Dialer{
Timeout: config.Timeout,
}).Dial,

Proxy: http.ProxyURL(config.ProxyURL),

TLSHandshakeTimeout: config.Timeout,
Expand Down
21 changes: 10 additions & 11 deletions implant/sliver/pivots/named-pipe_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package pivots

import (
"sync"
"time"

// {{if .Config.Debug}}
"log"
Expand All @@ -29,14 +30,20 @@ import (
"github.com/lesnuages/go-winio"
)

var (
namedpipePivotReadDeadline = 10 * time.Second
namedpipePivotWriteDeadline = 10 * time.Second
)

// CreateNamedPipePivotListener - Starts a named pipe listener
func CreateNamedPipePivotListener(address string, upstream chan<- *pb.Envelope) (*PivotListener, error) {
fullName := "\\\\.\\pipe\\" + address
ln, err := winio.ListenPipe(fullName, &winio.PipeConfig{
//SecurityDescriptor: "",
RemoteClientMode: true,
})
// {{if .Config.Debug}}
log.Printf("Listening on %s", fullName)
log.Printf("Listening on named pipe %s", fullName)
// {{end}}
if err != nil {
return nil, err
Expand All @@ -54,14 +61,6 @@ func CreateNamedPipePivotListener(address string, upstream chan<- *pb.Envelope)
}

func namedPipeAcceptConnections(pivotListener *PivotListener) {
// hostname, err := os.Hostname()
// if err != nil {
// // {{if .Config.Debug}}
// log.Printf("Failed to determine hostname %s", err)
// // {{end}}
// hostname = "."
// }
// namedPipe := strings.ReplaceAll(pivotListener.Listener.Addr().String(), ".", hostname)
for {
conn, err := pivotListener.Listener.Accept()
if err != nil {
Expand All @@ -72,8 +71,8 @@ func namedPipeAcceptConnections(pivotListener *PivotListener) {
conn: conn,
readMutex: &sync.Mutex{},
writeMutex: &sync.Mutex{},
readDeadline: tcpPivotReadDeadline,
writeDeadline: tcpPivotWriteDeadline,
readDeadline: namedpipePivotReadDeadline,
writeDeadline: namedpipePivotWriteDeadline,
upstream: pivotListener.Upstream,
Downstream: make(chan *pb.Envelope),
}
Expand Down
7 changes: 5 additions & 2 deletions implant/sliver/pivots/pivots.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ var (

// MyPeerID - This implant's Peer ID, a per-execution instance ID
MyPeerID = generatePeerID()

pivotReadDeadline = 10 * time.Second
pivotWriteDeadline = 10 * time.Second
)

// generatePeerID - Generate a new pivot id
Expand Down Expand Up @@ -240,8 +243,8 @@ func (p *PivotListener) Start() {
conn: conn,
readMutex: &sync.Mutex{},
writeMutex: &sync.Mutex{},
readDeadline: tcpPivotReadDeadline,
writeDeadline: tcpPivotWriteDeadline,
readDeadline: pivotReadDeadline,
writeDeadline: pivotWriteDeadline,
upstream: p.Upstream,
Downstream: make(chan *pb.Envelope),
}
Expand Down
55 changes: 41 additions & 14 deletions implant/sliver/transports/pivotclients/namedpipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,57 @@ package pivotclients
import (
"net/url"
"time"

// {{if .Config.Debug}}
"log"
// {{end}}
)

var (
defaultNamedPipeDeadline = time.Second * 10
)

// NamedPipePivotOptions - Options for the NamedPipe pivot
type NamedPipePivotOptions struct {
Timeout time.Duration
ReadDeadline time.Duration
WriteDeadline time.Duration
}

// ParseNamedPipePivotOptions - Parse the options for the TCP pivot from a C2 URL
func ParseNamedPipePivotOptions(uri *url.URL) *NamedPipePivotOptions {
readDeadline, err := time.ParseDuration(uri.Query().Get("read-deadline"))
if err != nil {
readDeadline = defaultNamedPipeDeadline
opts := &NamedPipePivotOptions{}
if readDeadline, err := time.ParseDuration(uri.Query().Get("read-deadline")); err == nil {
opts.ReadDeadline = readDeadline
} else {
// {{if .Config.Debug}}
if uri.Query().Get("read-deadline") != "" {
log.Printf("failed to parse read-deadline: %s", err)
}
// {{end}}
opts.ReadDeadline = defaultNamedPipeDeadline
}
writeDeadline, err := time.ParseDuration(uri.Query().Get("write-deadline"))
if err != nil {
writeDeadline = defaultNamedPipeDeadline
if writeDeadline, err := time.ParseDuration(uri.Query().Get("write-deadline")); err == nil {
opts.WriteDeadline = writeDeadline
} else {
// {{if .Config.Debug}}
if uri.Query().Get("write-deadline") != "" {
log.Printf("failed to parse write-deadline: %s", err)
}
// {{end}}
opts.WriteDeadline = defaultNamedPipeDeadline
}
return &NamedPipePivotOptions{
ReadDeadline: readDeadline,
WriteDeadline: writeDeadline,

if timeout, err := time.ParseDuration(uri.Query().Get("timeout")); err == nil {
opts.Timeout = timeout
} else {
// {{if .Config.Debug}}
if uri.Query().Get("timeout") != "" {
log.Printf("failed to parse timeout: %s", err)
}
// {{end}}
opts.Timeout = defaultNamedPipeDeadline
}
}

// NamedPipePivotOptions - Options for the NamedPipe pivot
type NamedPipePivotOptions struct {
ReadDeadline time.Duration
WriteDeadline time.Duration
return opts
}
18 changes: 7 additions & 11 deletions implant/sliver/transports/pivotclients/namedpipe_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ import (

// NamedPipePivotStartSession - Start a TCP pivot session with a peer
func NamedPipePivotStartSession(uri *url.URL, opts *NamedPipePivotOptions) (*NetConnPivotClient, error) {
address := uri.String()
address = strings.TrimSuffix(address, "namedpipe://")
address = "\\\\" + strings.ReplaceAll(address, "/", "\\")
address := "\\\\" + uri.Hostname() + strings.Replace(uri.Path, "/", "\\", -1)
// {{if .Config.Debug}}
log.Print("Pivot named pipe address: ", address)
log.Printf("Pivot named pipe address: %s", address)
log.Printf("Options: %+v", opts)
// {{end}}
conn, err := winio.DialPipe(address, nil)
if err != nil {
// {{if .Config.Debug}}
log.Printf("Failed to connect to named pipe: %s", err)
// {{end}}
return nil, err
}

Expand All @@ -53,17 +55,11 @@ func NamedPipePivotStartSession(uri *url.URL, opts *NamedPipePivotOptions) (*Net
readDeadline: opts.ReadDeadline,
writeDeadline: opts.WriteDeadline,
}
err = pivot.peerKeyExchange()
err = pivot.KeyExchange()
if err != nil {
conn.Close()
return nil, err
}
err = pivot.serverKeyExchange()
if err != nil {
conn.Close()
return nil, err
}

return pivot, nil
}

Expand Down
18 changes: 9 additions & 9 deletions implant/sliver/transports/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func StartConnectionLoop(c2s []string, abort <-chan struct{}) <-chan *Connection
// *** Named Pipe ***
// {{if .Config.NamePipec2Enabled}}
connection, err = namedPipeConnect(uri)
if err == nil {
if err != nil {
// {{if .Config.Debug}}
log.Printf("[namedpipe] Connection failed %s", err)
// {{end}}
Expand Down Expand Up @@ -717,7 +717,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
IsOpen: true,
cleanup: func() {
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] lost connection, cleanup...")
log.Printf("[tcp pivot] lost connection, cleanup...")
// {{end}}
pingCtrl <- struct{}{}
close(send)
Expand All @@ -728,7 +728,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {

connection.Stop = func() error {
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] Stop()")
log.Printf("[tcp pivot] Stop()")
// {{end}}
connection.Cleanup()
return nil
Expand Down Expand Up @@ -762,7 +762,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
}
case <-time.After(time.Minute):
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] server ping...")
log.Printf("[tcp pivot] server ping...")
// {{end}}
data, _ := proto.Marshal(&pb.PivotPing{
Nonce: uint32(time.Now().UnixNano()),
Expand All @@ -781,7 +781,7 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
}()
for envelope := range send {
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] send loop envelope type %d\n", envelope.Type)
log.Printf("[tcp pivot] send loop envelope type %d\n", envelope.Type)
// {{end}}
pivot.WriteEnvelope(envelope)
}
Expand All @@ -796,26 +796,26 @@ func tcpPivotConnect(uri *url.URL) (*Connection, error) {
}
if err != nil {
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] read envelope error: %s", err)
log.Printf("[tcp pivot] read envelope error: %s", err)
// {{end}}
continue
}
if envelope == nil {
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] read nil envelope")
log.Printf("[tcp pivot] read nil envelope")
// {{end}}
continue
}
if envelope.Type == pb.MsgPivotPeerPing {
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] received peer pong")
log.Printf("[tcp pivot] received peer pong")
// {{end}}
continue
}
if err == nil {
recv <- envelope
// {{if .Config.Debug}}
log.Printf("[tcp-pivot] Receive loop envelope type %d\n", envelope.Type)
log.Printf("[tcp pivot] Receive loop envelope type %d\n", envelope.Type)
// {{end}}
}
}
Expand Down
Loading

0 comments on commit b5d1e9a

Please sign in to comment.