diff --git a/client/command/filesystem.go b/client/command/filesystem.go index 967df338a..979079d8f 100644 --- a/client/command/filesystem.go +++ b/client/command/filesystem.go @@ -225,10 +225,6 @@ func cat(ctx *grumble.Context, rpc RPCServer) { fmt.Printf(Warn+"Error: %s", resp.Err) return } - if resp.Err != "" { - fmt.Printf(Warn+"Error: %s", resp.Err) - return - } download := &sliverpb.Download{} proto.Unmarshal(resp.Data, download) @@ -353,10 +349,6 @@ func upload(ctx *grumble.Context, rpc RPCServer) { return } - if err != nil { - fmt.Printf(Warn+"Unmarshaling envelope error: %v\n", err) - return - } upload := &sliverpb.Upload{} err = proto.Unmarshal(resp.Data, upload) if err != nil { diff --git a/client/command/job.go b/client/command/job.go index 405c68ac9..eafc58c11 100644 --- a/client/command/job.go +++ b/client/command/job.go @@ -19,10 +19,11 @@ func jobs(ctx *grumble.Context, rpc RPCServer) { Type: clientpb.MsgJobs, Data: []byte{}, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "Command timeout\n") + if resp.Err != "" { + fmt.Printf(Warn+"Error: %s\n", resp.Err) return } + jobs := &clientpb.Jobs{} proto.Unmarshal(resp.Data, jobs) @@ -72,10 +73,6 @@ func startMTLSListener(ctx *grumble.Context, rpc RPCServer) { Type: clientpb.MsgMtls, Data: data, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "Command timeout\n") - return - } if resp.Err != "" { fmt.Printf(Warn+"Failed to start job %s\n", resp.Err) return @@ -102,10 +99,6 @@ func startDNSListener(ctx *grumble.Context, rpc RPCServer) { Type: clientpb.MsgDns, Data: data, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "Command timeout\n") - return - } if resp.Err != "" { fmt.Printf(Warn+"Failed to start job %s\n", resp.Err) return @@ -130,10 +123,6 @@ func startHTTPSListener(ctx *grumble.Context, rpc RPCServer) { Type: clientpb.MsgHttps, Data: data, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "Command timeout\n") - return - } if resp.Err != "" { fmt.Printf(Warn+"Failed to start job %s\n", resp.Err) return @@ -157,10 +146,6 @@ func startHTTPListener(ctx *grumble.Context, rpc RPCServer) { Type: clientpb.MsgHttp, Data: data, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "Command timeout\n") - return - } if resp.Err != "" { fmt.Printf(Warn+"Failed to start job %s\n", resp.Err) return diff --git a/client/command/shell.go b/client/command/shell.go index 31c1f26a0..01621200a 100644 --- a/client/command/shell.go +++ b/client/command/shell.go @@ -42,10 +42,6 @@ func shell(ctx *grumble.Context, server *core.SliverServer) { Type: sliverpb.MsgShellReq, Data: shellReqData, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "Error: Server did not respond to request") - return - } if resp.Err != "" { fmt.Printf(Warn+"Error: %s", resp.Err) return diff --git a/client/command/sliver.go b/client/command/sliver.go index 411aa88a4..26f6a0314 100644 --- a/client/command/sliver.go +++ b/client/command/sliver.go @@ -32,8 +32,8 @@ func sessions(ctx *grumble.Context, rpc RPCServer) { Type: clientpb.MsgSessions, Data: []byte{}, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "Command timeout\n") + if resp.Err != "" { + fmt.Printf(Warn+"Error: %s\n", resp.Err) return } sessions := &clientpb.Sessions{} @@ -142,10 +142,6 @@ func kill(ctx *grumble.Context, rpc RPCServer) { Type: sliverpb.MsgKill, Data: data, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "No response from server\n") - return - } if resp.Err != "" { fmt.Printf(Warn+"%s\n", resp.Err) @@ -283,10 +279,6 @@ func compile(config *clientpb.SliverConfig, save string, rpc RPCServer) { Data: generateReq, }, 1200*time.Second) // TODO: make timeout a parameter ctrl <- true - if resp == nil { - fmt.Printf(Warn + "No response from server\n") - return - } if resp.Err != "" { fmt.Printf(Warn+"%s\n", resp.Err) return @@ -430,10 +422,6 @@ func newProfile(ctx *grumble.Context, rpc RPCServer) { Type: clientpb.MsgNewProfile, Data: data, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "No response from server\n") - return - } if resp.Err != "" { fmt.Printf(Warn+"%s\n", resp.Err) } else { @@ -445,10 +433,6 @@ func getSliverProfiles(rpc RPCServer) *map[string]*clientpb.Profile { resp := <-rpc(&sliverpb.Envelope{ Type: clientpb.MsgProfiles, }, defaultTimeout) - if resp == nil { - fmt.Printf(Warn + "No response from server\n") - return nil - } if resp.Err != "" { fmt.Printf(Warn+"%s\n", resp.Err) return nil diff --git a/client/core/core.go b/client/core/core.go index 80c73c5df..765b788ec 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -176,7 +176,7 @@ func (ss *SliverServer) RPC(envelope *sliverpb.Envelope, timeout time.Duration) case respEnvelope := <-resp: respCh <- respEnvelope case <-time.After(timeout): - respCh <- nil + respCh <- &sliverpb.Envelope{Err: "Timeout"} } }() return respCh diff --git a/server/c2/tcp-http.go b/server/c2/tcp-http.go index 09929790f..f179a7521 100644 --- a/server/c2/tcp-http.go +++ b/server/c2/tcp-http.go @@ -163,11 +163,14 @@ func (s *SliverHTTPC2) router() *mux.Router { // .js = poll // .png = stop - router.HandleFunc("/{rpath:.*\\.txt$}", s.rsaKeyHandler).Methods("GET") - router.HandleFunc("/{rpath:.*\\.css$}", s.startSessionHandler).Methods("GET", "POST") - router.HandleFunc("/{rpath:.*\\.php$}", s.sessionHandler).Methods("GET", "POST") - router.HandleFunc("/{rpath:.*\\.js$}", s.pollHandler).Methods("GET") - router.HandleFunc("/{rpath:.*\\.png$}", s.stopHandler).Methods("GET") + router.HandleFunc("/{rpath:.*\\.txt$}", s.rsaKeyHandler).MatcherFunc(filterAgent).Methods(http.MethodGet) + router.HandleFunc("/{rpath:.*\\.css$}", s.startSessionHandler).MatcherFunc(filterAgent).Methods(http.MethodGet, http.MethodPost) + router.HandleFunc("/{rpath:.*\\.php$}", s.sessionHandler).MatcherFunc(filterAgent).Methods(http.MethodGet, http.MethodPost) + router.HandleFunc("/{rpath:.*\\.js$}", s.pollHandler).MatcherFunc(filterAgent).Methods(http.MethodGet) + router.HandleFunc("/{rpath:.*\\.png$}", s.stopHandler).MatcherFunc(filterAgent).Methods(http.MethodGet) + + // Request does not match the C2 profile so we pass it to the default handler + router.HandleFunc("{rpath:.*}", defaultHandler).Methods(http.MethodGet, http.MethodPost) router.Use(loggingMiddleware) router.Use(defaultRespHeaders) @@ -175,6 +178,15 @@ func (s *SliverHTTPC2) router() *mux.Router { return router } +// This filters requests that do not have the correct "User-agent" header +func filterAgent(req *http.Request, rm *mux.RouteMatch) bool { + userAgent := req.Header["User-Agent"] + if 0 < len(userAgent) && strings.HasPrefix(userAgent[0], "Mozillа") { + return true + } + return false +} + func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { log.Printf("[http] %v", req.RequestURI) @@ -207,6 +219,10 @@ func defaultRespHeaders(next http.Handler) http.Handler { }) } +func defaultHandler(resp http.ResponseWriter, req *http.Request) { + resp.WriteHeader(404) +} + // [ HTTP Handlers ] --------------------------------------------------------------- func (s *SliverHTTPC2) rsaKeyHandler(resp http.ResponseWriter, req *http.Request) { @@ -361,7 +377,7 @@ func (s *SliverHTTPC2) stopHandler(resp http.ResponseWriter, req *http.Request) func (s *SliverHTTPC2) getSession(req *http.Request) *HTTPSession { for _, cookie := range req.Cookies() { - log.Printf("[http] Cookie: %#v", cookie) + // log.Printf("[http] Cookie: %#v", cookie) if cookie.Name == sessionCookieName { session := s.Sessions.Get(cookie.Value) if session != nil { diff --git a/sliver/transports/tcp-http.go b/sliver/transports/tcp-http.go index 83ed7a979..4159153c5 100644 --- a/sliver/transports/tcp-http.go +++ b/sliver/transports/tcp-http.go @@ -40,6 +40,8 @@ import ( ) const ( + // IE 11 User-agent with a unicode 'a' + defaultUserAgent = "Mozillа/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko" defaultNetTimeout = time.Second * 60 defaultReqTimeout = time.Second * 60 // Long polling, we want a large timeout ) @@ -100,7 +102,8 @@ func (s *SliverHTTPClient) SessionInit() error { func (s *SliverHTTPClient) newHTTPRequest(method, uri string, body io.Reader) *http.Request { req, _ := http.NewRequest(method, uri, body) - req.Header.Set("User-Agent", "") + req.Header.Set("User-Agent", defaultUserAgent) + req.Header.Set("Accept-Language", "en-US") return req } @@ -111,17 +114,20 @@ func (s *SliverHTTPClient) getPublicKey() *rsa.PublicKey { // {{end}} req := s.newHTTPRequest(http.MethodGet, uri, nil) resp, err := s.Client.Do(req) - if err != nil || resp.StatusCode != 200 { + if err != nil { // {{if .Debug}} - log.Printf("Failed to fetch server public key") + log.Printf("[http] Failed to fetch server public key: %v", err) // {{end}} return nil } + // {{if .Debug}} + log.Printf("[http] <- %d Server key response", resp.StatusCode) + // {{end}} data, _ := ioutil.ReadAll(resp.Body) pubKeyBlock, _ := pem.Decode(data) if pubKeyBlock == nil { // {{if .Debug}} - log.Printf("Failed to parse certificate PEM") + log.Printf("[http] Failed to parse certificate PEM") // {{end}} return nil }