Skip to content

Commit

Permalink
[+] #28 Add tunnel function
Browse files Browse the repository at this point in the history
  • Loading branch information
WangYihang committed Jul 10, 2021
1 parent 5936ad8 commit dffd811
Show file tree
Hide file tree
Showing 7 changed files with 245 additions and 44 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4
github.com/rhysd/go-github-selfupdate v1.2.3
github.com/sevlyar/go-daemon v0.1.5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/gomega v1.4.2 h1:3mYCb7aPxS/RU7TI1y4rkEn1oKmPRjNJLNEXgw7MH2I=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI=
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
41 changes: 39 additions & 2 deletions lib/cli/dispatcher/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,52 @@ package dispatcher

import (
"fmt"
"strconv"
"strings"

"github.com/WangYihang/Platypus/lib/context"
"github.com/WangYihang/Platypus/lib/util/log"
)

func (dispatcher Dispatcher) Tunnel(args []string) {
fmt.Println("TO BE IMPLEMENTED.")
if context.Ctx.Current == nil && context.Ctx.CurrentTermite == nil {
log.Error("Interactive session is not set, please use `Jump` command to set the interactive Interact")
return
}

if context.Ctx.CurrentTermite != nil {
if len(args) != 3 {
log.Error("Arguments error, use `Help Tunnel` to get more information")
dispatcher.TunnelHelp([]string{})
return
}

mode := args[0]
host := args[1]
port, err := strconv.ParseUint(args[2], 10, 16)

if err != nil {
log.Error("Invalid port: %s, use `Help Tunnel` to get more information", args[1])
dispatcher.TunnelHelp([]string{})
return
}

switch strings.ToLower(mode) {
case "create":
context.Ctx.CurrentTermite.CreateTunnel(host, uint16(port))
case "delete":
context.Ctx.CurrentTermite.DeleteTunnel(host, uint16(port))
}
}

if context.Ctx.Current != nil {
log.Error("Tunneling is not supported in plain reverse shell")
}
}

func (dispatcher Dispatcher) TunnelHelp(args []string) {
fmt.Println("Usage of Tunnel")
fmt.Println("\tTunnel [SRC] [DST]")
fmt.Println("\tTunnel [Create|Delete] [Host] [Port]")
}

func (dispatcher Dispatcher) TunnelDesc(args []string) {
Expand Down
39 changes: 39 additions & 0 deletions lib/context/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/WangYihang/Platypus/lib/util/str"
humanize "github.com/dustin/go-humanize"
"github.com/jedib0t/go-pretty/table"
"github.com/phayes/freeport"
)

type WebSocketMessage struct {
Expand Down Expand Up @@ -542,6 +543,44 @@ func TermiteMessageDispatcher(client *TermiteClient) {
} else {
log.Error("No such key")
}
case message.TUNNEL_CONNECTED:
target := msg.Body.(*message.BodyTunnelConnected).Target
port, _ := freeport.GetFreePort()
localAddress := fmt.Sprintf("0.0.0.0:%d", port)
tunnel, err := net.Listen("tcp", localAddress)
if err != nil {
log.Error(err.Error())
break
}
log.Info("%s -> %s", localAddress, target)
go func(target string, port int) {
conn, _ := tunnel.Accept()
Ctx.CurrentTermite.Tunnels[target] = &conn
log.Info("Server client tunnel connected: %v", conn)
for {
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
log.Error(err.Error())
break
}
if n > 0 {
log.Info(">> %v", buf[0:n])
Ctx.CurrentTermite.WriteTunnel(target, buf[0:n])
}
}
}(target, port)
case message.TUNNEL_DATA:
target := msg.Body.(*message.BodyTunnelData).Target
data := msg.Body.(*message.BodyTunnelData).Data
log.Info("%s, %v, connected", target, data)

if conn, exists := Ctx.CurrentTermite.Tunnels[target]; exists {
(*conn).Write(data)
} else {
log.Error("No such tunnel")
}

}
}
}
Expand Down
83 changes: 72 additions & 11 deletions lib/context/termite.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,18 @@ type Process struct {

type TermiteClient struct {
conn net.Conn
Hash string `json:"hash"`
Host string `json:"host"`
Port uint16 `json:"port"`
Alias string `json:"alias"`
User string `json:"user"`
OS oss.OperatingSystem `json:"os"`
NetworkInterfaces map[string]string `json:"network_interfaces"`
Python2 string `json:"python2"`
Python3 string `json:"python3"`
TimeStamp time.Time `json:"timestamp"`
DisableHistory bool `json:"disable_hisory"`
Hash string `json:"hash"`
Host string `json:"host"`
Port uint16 `json:"port"`
Alias string `json:"alias"`
User string `json:"user"`
OS oss.OperatingSystem `json:"os"`
NetworkInterfaces map[string]string `json:"network_interfaces"`
Python2 string `json:"python2"`
Python3 string `json:"python3"`
TimeStamp time.Time `json:"timestamp"`
DisableHistory bool `json:"disable_hisory"`
Tunnels map[string]*net.Conn `json:"tunnels"`
server *TCPServer
EncoderLock *sync.Mutex
DecoderLock *sync.Mutex
Expand Down Expand Up @@ -86,6 +87,7 @@ func CreateTermiteClient(conn net.Conn, server *TCPServer, disableHistory bool)
Processes: map[string]*Process{},
CurrentProcessKey: "",
DisableHistory: disableHistory,
Tunnels: map[string]*net.Conn{},
}
}

Expand Down Expand Up @@ -332,6 +334,65 @@ func (c *TermiteClient) GetUsername() string {
return username
}

func (c *TermiteClient) CreateTunnel(host string, port uint16) {
log.Info("Connecting to %s:%d", host, port)

c.AtomLock.Lock()
defer func() { c.AtomLock.Unlock() }()

c.EncoderLock.Lock()
err := c.Encoder.Encode(message.Message{
Type: message.TUNNEL_CONNECT,
Body: message.BodyTunnelConnect{
Target: fmt.Sprintf("%s:%d", host, port),
},
})
c.EncoderLock.Unlock()

if err != nil {
log.Error("Network error: %s", err)
}
}

func (c *TermiteClient) DeleteTunnel(host string, port uint16) {
log.Info("Disconnecting to %s:%d", host, port)

c.AtomLock.Lock()
defer func() { c.AtomLock.Unlock() }()

c.EncoderLock.Lock()
err := c.Encoder.Encode(message.Message{
Type: message.TUNNEL_DISCONNECT,
Body: message.BodyTunnelDisconnect{
Target: fmt.Sprintf("%s:%d", host, port),
},
})
c.EncoderLock.Unlock()

if err != nil {
log.Error("Network error: %s", err)
}
}

func (c *TermiteClient) WriteTunnel(target string, data []byte) {
c.AtomLock.Lock()
defer func() { c.AtomLock.Unlock() }()

c.EncoderLock.Lock()
err := c.Encoder.Encode(message.Message{
Type: message.TUNNEL_DATA,
Body: message.BodyTunnelData{
Target: target,
Data: data,
},
})
c.EncoderLock.Unlock()

if err != nil {
log.Error("Network error: %s", err)
}
}

func (c *TermiteClient) makeHash(hashFormat string) string {
data := ""
if c.OS == oss.Linux {
Expand Down
25 changes: 25 additions & 0 deletions lib/util/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ const (
PROCESS_STARTED
PROCESS_STOPED
CLIENT_INFO

// Tunnel
TUNNEL_CONNECT
TUNNEL_CONNECTED
TUNNEL_DATA
TUNNEL_DISCONNECT
)

type Message struct {
Expand Down Expand Up @@ -72,6 +78,21 @@ type BodyTerminateProcess struct {
Key string
}

type BodyTunnelConnect struct {
Target string
}
type BodyTunnelConnected struct {
Target string
}
type BodyTunnelData struct {
Target string
Data []byte
}

type BodyTunnelDisconnect struct {
Target string
}

func RegisterGob() {
gob.Register(&BodyStdio{})
gob.Register(&BodyWindowSize{})
Expand All @@ -82,4 +103,8 @@ func RegisterGob() {
gob.Register(&BodyDuplicateClient{})
gob.Register(&BodyClientInfo{})
gob.Register(&BodyTerminateProcess{})
gob.Register(&BodyTunnelConnect{})
gob.Register(&BodyTunnelConnected{})
gob.Register(&BodyTunnelData{})
gob.Register(&BodyTunnelDisconnect{})
}
Loading

0 comments on commit dffd811

Please sign in to comment.