Skip to content

Commit

Permalink
Implemented server-side seq numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
moloch-- committed Dec 5, 2020
1 parent 5c29428 commit 77e6b07
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 17 deletions.
17 changes: 11 additions & 6 deletions server/core/tunnels.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,16 @@ var (
// with an identifier, these tunnels are full duplex. The server doesn't really
// care what data gets passed back and forth it just facilitates the connection
type Tunnel struct {
ID uint64
SessionID uint32
ToImplant chan []byte
FromImplant chan []byte
Client rpcpb.SliverRPC_TunnelDataServer
ID uint64
SessionID uint32

ToImplant chan []byte
ToImplantSequence uint64

FromImplant chan *sliverpb.TunnelData
FromImplantSequence uint64

Client rpcpb.SliverRPC_TunnelDataServer
}

type tunnels struct {
Expand All @@ -63,7 +68,7 @@ func (t *tunnels) Create(sessionID uint32) *Tunnel {
ID: tunnelID,
SessionID: session.ID,
ToImplant: make(chan []byte),
FromImplant: make(chan []byte),
FromImplant: make(chan *sliverpb.TunnelData),
}
t.mutex.Lock()
defer t.mutex.Unlock()
Expand Down
2 changes: 1 addition & 1 deletion server/handlers/sessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func tunnelDataHandler(session *core.Session, data []byte) {
tunnel := core.Tunnels.Get(tunnelData.TunnelID)
if tunnel != nil {
if session.ID == tunnel.SessionID {
tunnel.FromImplant <- tunnelData.GetData()
tunnel.FromImplant <- tunnelData
} else {
handlerLog.Warnf("Warning: Session %d attempted to send data on tunnel it did not own", session.ID)
}
Expand Down
37 changes: 28 additions & 9 deletions server/rpc/rpc-tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import (

var (
tunnelLog = log.NamedLogger("rpc", "tunnel")

fromImplantCache = map[uint64]map[uint64]*sliverpb.TunnelData{}
)

// CreateTunnel - Create a new tunnel on the server, however based on only this request there's
Expand All @@ -46,6 +48,7 @@ func (s *Server) CreateTunnel(ctx context.Context, req *sliverpb.Tunnel) (*slive
if tunnel == nil {
return nil, ErrTunnelInitFailure
}
fromImplantCache[tunnel.ID] = map[uint64]*sliverpb.TunnelData{}
return &sliverpb.Tunnel{
SessionID: session.ID,
TunnelID: tunnel.ID,
Expand All @@ -55,6 +58,11 @@ func (s *Server) CreateTunnel(ctx context.Context, req *sliverpb.Tunnel) (*slive
// CloseTunnel - Client requests we close a tunnel
func (s *Server) CloseTunnel(ctx context.Context, req *sliverpb.Tunnel) (*commonpb.Empty, error) {
err := core.Tunnels.Close(req.TunnelID)

if _, ok := fromImplantCache[req.TunnelID]; ok {
delete(fromImplantCache, req.TunnelID)
}

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -89,15 +97,22 @@ func (s *Server) TunnelData(stream rpcpb.SliverRPC_TunnelDataServer) error {
})

go func() {
for data := range tunnel.FromImplant {
tunnelLog.Debugf("Tunnel %d: From implant %d byte(s)", tunnel.ID, len(data))
tunnel.Client.Send(&sliverpb.TunnelData{
TunnelID: tunnel.ID,
SessionID: tunnel.SessionID,
Data: data,
Closed: false,
})
tunnelLog.Debugf("Sent data to client %v", tunnel.Client)
for tunnelData := range tunnel.FromImplant {
tunnelLog.Debugf("Tunnel %d: From implant %d byte(s)", tunnel.ID, len(tunnelData.Data))
cache, ok := fromImplantCache[tunnel.ID]
if ok {
cache[tunnelData.Sequence] = tunnelData
}
for recv, ok := cache[tunnel.FromImplantSequence]; ok; recv, ok = cache[tunnel.FromImplantSequence] {
tunnel.Client.Send(&sliverpb.TunnelData{
TunnelID: tunnel.ID,
SessionID: tunnel.SessionID,
Data: recv.Data,
Closed: false,
})
delete(cache, tunnel.FromImplantSequence)
tunnel.FromImplantSequence++
}
}
tunnelLog.Debugf("Closing tunnel %d (To Client)", tunnel.ID)
tunnel.Client.Send(&sliverpb.TunnelData{
Expand All @@ -112,18 +127,22 @@ func (s *Server) TunnelData(stream rpcpb.SliverRPC_TunnelDataServer) error {
for data := range tunnel.ToImplant {
tunnelLog.Debugf("Tunnel %d: To implant %d byte(s)", tunnel.ID, len(data))
data, _ := proto.Marshal(&sliverpb.TunnelData{
Sequence: tunnel.ToImplantSequence,
TunnelID: tunnel.ID,
SessionID: tunnel.SessionID,
Data: data,
Closed: false,
})
tunnel.ToImplantSequence++
session.Send <- &sliverpb.Envelope{
Type: sliverpb.MsgTunnelData,
Data: data,
}

}
tunnelLog.Debugf("Closing tunnel %d (To Implant) ...", tunnel.ID)
data, _ := proto.Marshal(&sliverpb.TunnelData{
Sequence: tunnel.ToImplantSequence, // Shouldn't need to increment since this will close the tunnel
TunnelID: tunnel.ID,
SessionID: tunnel.SessionID,
Data: make([]byte, 0),
Expand Down
2 changes: 1 addition & 1 deletion sliver/handlers/generic-tun-handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func tunnelDataHandler(envelope *sliverpb.Envelope, connection *transports.Conne
cache := tunnelDataCache[tunnel.ID]
for recv, ok := cache[tunnel.ReadSequence]; ok; recv, ok = cache[tunnel.ReadSequence] {
// {{if .Config.Debug}}
log.Printf("[tunnel] Write %d bytes to tunnel %d (read seq: %d)", recv.TunnelID, recv.Sequence)
log.Printf("[tunnel] Write %d bytes to tunnel %d (read seq: %d)", len(recv.Data), recv.TunnelID, recv.Sequence)
// {{end}}
tunnel.Writer.Write(recv.Data)

Expand Down

0 comments on commit 77e6b07

Please sign in to comment.