diff --git a/caplets/http-req-dump.js b/caplets/http-req-dump.js index 184060ec..6af290d9 100644 --- a/caplets/http-req-dump.js +++ b/caplets/http-req-dump.js @@ -118,7 +118,7 @@ function dumpRaw(req) { } function onRequest(req, res) { - log( BOLD(req.Client), " > ", B(req.Method), req.Hostname + req.Path + ( req.Query ? "?" + req.Query : '') ); + log( BOLD(req.Client), " > ", B(req.Method), " " + req.Hostname + req.Path + ( req.Query ? "?" + req.Query : '') ); dumpHeaders(req); diff --git a/modules/api_rest.go b/modules/api_rest.go index 704397d0..ca512505 100644 --- a/modules/api_rest.go +++ b/modules/api_rest.go @@ -145,33 +145,30 @@ func (api *RestAPI) Configure() error { } func (api *RestAPI) Start() error { - if err := api.Configure(); err != nil { + if api.Running() == true { + return session.ErrAlreadyStarted + } else if err := api.Configure(); err != nil { return err } - if api.Running() == false { - api.SetRunning(true) - go func() { - log.Info("API server starting on https://%s", api.server.Addr) - err := api.server.ListenAndServeTLS(api.certFile, api.keyFile) - if err != nil && err != http.ErrServerClosed { - panic(err) - } - }() + api.SetRunning(true) + go func() { + log.Info("API server starting on https://%s", api.server.Addr) + err := api.server.ListenAndServeTLS(api.certFile, api.keyFile) + if err != nil && err != http.ErrServerClosed { + panic(err) + } + }() - return nil - } - - return fmt.Errorf("REST API server already started.") + return nil } func (api *RestAPI) Stop() error { - if api.Running() == true { - api.SetRunning(false) - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - defer cancel() - return api.server.Shutdown(ctx) - } else { - return fmt.Errorf("REST API server already stopped.") + if api.Running() == false { + return session.ErrAlreadyStopped } + api.SetRunning(false) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + return api.server.Shutdown(ctx) } diff --git a/modules/arp_spoof.go b/modules/arp_spoof.go index adb205d4..56021b93 100644 --- a/modules/arp_spoof.go +++ b/modules/arp_spoof.go @@ -15,13 +15,15 @@ import ( type ArpSpoofer struct { session.SessionModule - done chan bool + done chan bool + addresses []net.IP } func NewArpSpoofer(s *session.Session) *ArpSpoofer { p := &ArpSpoofer{ SessionModule: session.NewSessionModule("arp.spoof", s), done: make(chan bool), + addresses: make([]net.IP, 0), } p.AddParam(session.NewStringParameter("arp.spoof.targets", session.ParamSubnet, "", "IP addresses to spoof.")) @@ -99,8 +101,8 @@ func (p *ArpSpoofer) getMAC(ip net.IP, probe bool) (net.HardwareAddr, error) { return hw, nil } -func (p *ArpSpoofer) sendArp(addresses []net.IP, saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) { - for _, ip := range addresses { +func (p *ArpSpoofer) sendArp(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) { + for _, ip := range p.addresses { if p.shouldSpoof(ip) == false { log.Debug("Skipping address %s from ARP spoofing.", ip) continue @@ -127,80 +129,69 @@ func (p *ArpSpoofer) sendArp(addresses []net.IP, saddr net.IP, smac net.Hardware } func (p *ArpSpoofer) unSpoof() error { + from := p.Session.Gateway.IP + from_hw := p.Session.Gateway.HW + + log.Info("Restoring ARP cache of %d targets.", len(p.addresses)) + + p.sendArp(from, from_hw, false, false) + + return nil +} + +func (p *ArpSpoofer) Configure() error { + var err error var targets string - if err, v := p.Param("arp.spoof.targets").Get(p.Session); err != nil { + if err, targets = p.StringParam("arp.spoof.targets"); err != nil { return err - } else { - targets = v.(string) } list, err := iprange.Parse(targets) if err != nil { return fmt.Errorf("Error while parsing arp.spoof.targets variable '%s': %s.", targets, err) } - addresses := list.Expand() - - from := p.Session.Gateway.IP - from_hw := p.Session.Gateway.HW - - log.Info("Restoring ARP cache of %d targets (%s).", len(addresses), targets) - - p.sendArp(addresses, from, from_hw, false, false) - + p.addresses = list.Expand() return nil } func (p *ArpSpoofer) Start() error { - if p.Running() == false { - var err error - var targets string - - if err, targets = p.StringParam("arp.spoof.targets"); err != nil { - return err - } - - list, err := iprange.Parse(targets) - if err != nil { - return fmt.Errorf("Error while parsing arp.spoof.targets variable '%s': %s.", targets, err) - } - addresses := list.Expand() - - p.SetRunning(true) - - go func() { - - from := p.Session.Gateway.IP - from_hw := p.Session.Interface.HW - - log.Info("ARP spoofer started, probing %d targets (%s).", len(addresses), targets) - - for p.Running() { - p.sendArp(addresses, from, from_hw, true, false) - time.Sleep(1 * time.Second) - } - - p.done <- true - }() - - return nil - } else { - return fmt.Errorf("ARP spoofer already started.") + if p.Running() == true { + return session.ErrAlreadyStarted + } else if err := p.Configure(); err != nil { + return err } + + p.SetRunning(true) + go func() { + from := p.Session.Gateway.IP + from_hw := p.Session.Interface.HW + + log.Info("ARP spoofer started, probing %d targets.", len(p.addresses)) + + for p.Running() { + p.sendArp(from, from_hw, true, false) + time.Sleep(1 * time.Second) + } + + p.done <- true + }() + + return nil } func (p *ArpSpoofer) Stop() error { - if p.Running() == true { - p.SetRunning(false) - - log.Info("Waiting for ARP spoofer to stop ...") - - <-p.done - - p.unSpoof() - - return nil - } else { - return fmt.Errorf("ARP spoofer already stopped.") + if p.Running() == false { + return session.ErrAlreadyStopped } + + log.Info("Waiting for ARP spoofer to stop ...") + + p.SetRunning(false) + + <-p.done + + p.unSpoof() + + return nil } diff --git a/modules/events_stream.go b/modules/events_stream.go index cabf68ec..18b65fc8 100644 --- a/modules/events_stream.go +++ b/modules/events_stream.go @@ -10,12 +10,14 @@ import ( type EventsStream struct { session.SessionModule - quit chan bool + filter string + quit chan bool } func NewEventsStream(s *session.Session) *EventsStream { stream := &EventsStream{ SessionModule: session.NewSessionModule("events.stream", s), + filter: "", quit: make(chan bool), } @@ -58,52 +60,55 @@ func (s EventsStream) Author() string { return "Simone Margaritelli " } +func (s *EventsStream) Configure() error { + var err error + if err, s.filter = s.StringParam("events.stream.filter"); err != nil { + return err + } + return nil +} + func (s *EventsStream) Start() error { - if s.Running() == false { - var err error - var filter string - - if err, filter = s.StringParam("events.stream.filter"); err != nil { - return err - } - - s.SetRunning(true) - - go func() { - for { - var e session.Event - select { - case e = <-s.Session.Events.NewEvents: - if filter == "" || strings.Contains(e.Tag, filter) { - tm := e.Time.Format("2006-01-02 15:04:05") - - if e.Tag == "sys.log" { - fmt.Printf("[%s] [%s] (%s) %s\n", tm, core.Green(e.Tag), e.Label(), e.Data.(session.LogMessage).Message) - } else { - fmt.Printf("[%s] [%s] %v\n", tm, core.Green(e.Tag), e.Data) - } - - s.Session.Input.Refresh() - } - break - - case <-s.quit: - return - } - } - }() - - return nil + if s.Running() == true { + return session.ErrAlreadyStarted + } else if err := s.Configure(); err != nil { + return err } - return fmt.Errorf("Events stream already started.") + s.SetRunning(true) + + go func() { + for { + var e session.Event + select { + case e = <-s.Session.Events.NewEvents: + if s.filter == "" || strings.Contains(e.Tag, s.filter) { + tm := e.Time.Format("2006-01-02 15:04:05") + + if e.Tag == "sys.log" { + fmt.Printf("[%s] [%s] (%s) %s\n", tm, core.Green(e.Tag), e.Label(), e.Data.(session.LogMessage).Message) + } else { + fmt.Printf("[%s] [%s] %v\n", tm, core.Green(e.Tag), e.Data) + } + + s.Session.Input.Refresh() + } + break + + case <-s.quit: + return + } + } + }() + + return nil } func (s *EventsStream) Stop() error { - if s.Running() == true { - s.SetRunning(false) - s.quit <- true - return nil + if s.Running() == false { + return session.ErrAlreadyStopped } - return fmt.Errorf("Events stream already stopped.") + s.SetRunning(false) + s.quit <- true + return nil } diff --git a/modules/http_proxy.go b/modules/http_proxy.go index e8e16dfd..468add08 100644 --- a/modules/http_proxy.go +++ b/modules/http_proxy.go @@ -116,6 +116,28 @@ func NewHttpProxy(s *session.Session) *HttpProxy { return p } +func (p *HttpProxy) doProxy(req *http.Request) bool { + blacklist := []string{ + "localhost", + "127.0.0.1", + p.address, + } + + if req.Host == "" { + log.Error("Got request with empty host: %v", req) + return false + } + + for _, blacklisted := range blacklist { + if strings.HasPrefix(req.Host, blacklisted) { + log.Error("Got request with blacklisted host: %s", req.Host) + return false + } + } + + return true +} + func (p *HttpProxy) Name() string { return "http.proxy" } @@ -128,16 +150,12 @@ func (p *HttpProxy) Author() string { return "Simone Margaritelli " } -func (p *HttpProxy) Start() error { +func (p *HttpProxy) Configure() error { var err error var http_port int var proxy_port int var scriptPath string - if p.Running() == true { - return fmt.Errorf("HTTP proxy already started.") - } - if err, p.address = p.StringParam("http.proxy.address"); err != nil { return err } @@ -160,6 +178,8 @@ func (p *HttpProxy) Start() error { } } + p.server = http.Server{Addr: fmt.Sprintf("%s:%d", p.address, proxy_port), Handler: p.proxy} + if p.Session.Firewall.IsForwardingEnabled() == false { log.Info("Enabling forwarding.") p.Session.Firewall.EnableForwarding(true) @@ -177,10 +197,18 @@ func (p *HttpProxy) Start() error { log.Debug("Applied redirection %s", p.redirection.String()) - address := fmt.Sprintf("%s:%d", p.address, proxy_port) - p.server = http.Server{Addr: address, Handler: p.proxy} + return nil +} + +func (p *HttpProxy) Start() error { + if p.Running() == true { + return session.ErrAlreadyStarted + } else if err := p.Configure(); err != nil { + return err + } + + p.SetRunning(true) go func() { - p.SetRunning(true) if err := p.server.ListenAndServe(); err != nil { p.SetRunning(false) log.Warning("%s", err) @@ -191,42 +219,20 @@ func (p *HttpProxy) Start() error { } func (p *HttpProxy) Stop() error { - if p.Running() == true { - p.SetRunning(false) - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - defer cancel() - p.server.Shutdown(ctx) - if p.redirection != nil { - log.Debug("Disabling redirection %s", p.redirection.String()) - if err := p.Session.Firewall.EnableRedirection(p.redirection, false); err != nil { - return err - } - p.redirection = nil + if p.Running() == false { + return session.ErrAlreadyStopped + } + p.SetRunning(false) + + if p.redirection != nil { + log.Debug("Disabling redirection %s", p.redirection.String()) + if err := p.Session.Firewall.EnableRedirection(p.redirection, false); err != nil { + return err } - return nil - } else { - return fmt.Errorf("HTTP proxy stopped.") + p.redirection = nil } -} - -func (p *HttpProxy) doProxy(req *http.Request) bool { - blacklist := []string{ - "localhost", - "127.0.0.1", - p.address, - } - - if req.Host == "" { - log.Error("Got request with empty host: %v", req) - return false - } - - for _, blacklisted := range blacklist { - if strings.HasPrefix(req.Host, blacklisted) { - log.Error("Got request with blacklisted host: %s", req.Host) - return false - } - } - - return true + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + return p.server.Shutdown(ctx) } diff --git a/modules/http_server.go b/modules/http_server.go index 2ac2a9c0..a775f495 100644 --- a/modules/http_server.go +++ b/modules/http_server.go @@ -88,33 +88,30 @@ func (httpd *HttpServer) Configure() error { } func (httpd *HttpServer) Start() error { - if err := httpd.Configure(); err != nil { + if httpd.Running() == true { + return session.ErrAlreadyStarted + } else if err := httpd.Configure(); err != nil { return err } - if httpd.Running() == false { - httpd.SetRunning(true) - go func() { - log.Info("httpd server starting on http://%s", httpd.server.Addr) - err := httpd.server.ListenAndServe() - if err != nil && err != http.ErrServerClosed { - panic(err) - } - }() + httpd.SetRunning(true) + go func() { + log.Info("httpd server starting on http://%s", httpd.server.Addr) + err := httpd.server.ListenAndServe() + if err != nil && err != http.ErrServerClosed { + panic(err) + } + }() - return nil - } - - return fmt.Errorf("httpd server already started.") + return nil } func (httpd *HttpServer) Stop() error { - if httpd.Running() == true { - httpd.SetRunning(false) - ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) - defer cancel() - return httpd.server.Shutdown(ctx) - } else { - return fmt.Errorf("httpd server already stopped.") + if httpd.Running() == false { + return session.ErrAlreadyStopped } + httpd.SetRunning(false) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + return httpd.server.Shutdown(ctx) } diff --git a/modules/net_probe.go b/modules/net_probe.go index 742204c7..e2b0d30c 100644 --- a/modules/net_probe.go +++ b/modules/net_probe.go @@ -13,6 +13,7 @@ import ( type Prober struct { session.SessionModule + throttle int } func NewProber(s *session.Session) *Prober { @@ -78,58 +79,60 @@ func (p *Prober) sendProbe(from net.IP, from_hw net.HardwareAddr, ip net.IP) { } } -func (p *Prober) Start() error { - if p.Running() == false { - var err error - var throttle int +func (p *Prober) Configure() error { + var err error + if err, p.throttle = p.IntParam("net.probe.throttle"); err != nil { + return err + } else { + log.Debug("Throttling packets of %d ms.", p.throttle) + } + return nil +} - if err, throttle = p.IntParam("net.probe.throttle"); err != nil { - return err - } else { - log.Debug("Throttling packets of %d ms.", throttle) +func (p *Prober) Start() error { + if p.Running() == true { + return session.ErrAlreadyStarted + } else if err := p.Configure(); err != nil { + return err + } + + p.SetRunning(true) + + go func() { + list, err := iprange.Parse(p.Session.Interface.CIDR()) + if err != nil { + log.Fatal("%s", err) } - p.SetRunning(true) + from := p.Session.Interface.IP + from_hw := p.Session.Interface.HW + addresses := list.Expand() - go func() { - list, err := iprange.Parse(p.Session.Interface.CIDR()) - if err != nil { - log.Fatal("%s", err) - } - - from := p.Session.Interface.IP - from_hw := p.Session.Interface.HW - addresses := list.Expand() - - for p.Running() { - for _, ip := range addresses { - if p.shouldProbe(ip) == false { - log.Debug("Skipping address %s from UDP probing.", ip) - continue - } - - p.sendProbe(from, from_hw, ip) - - if throttle > 0 { - time.Sleep(time.Duration(throttle) * time.Millisecond) - } + for p.Running() { + for _, ip := range addresses { + if p.shouldProbe(ip) == false { + log.Debug("Skipping address %s from UDP probing.", ip) + continue } - time.Sleep(5 * time.Second) - } - }() + p.sendProbe(from, from_hw, ip) - return nil - } else { - return fmt.Errorf("Network prober already started.") - } + if p.throttle > 0 { + time.Sleep(time.Duration(p.throttle) * time.Millisecond) + } + } + + time.Sleep(5 * time.Second) + } + }() + + return nil } func (p *Prober) Stop() error { - if p.Running() == true { - p.SetRunning(false) - return nil - } else { - return fmt.Errorf("Network prober already stopped.") + if p.Running() == false { + return session.ErrAlreadyStopped } + p.SetRunning(false) + return nil } diff --git a/modules/net_recon.go b/modules/net_recon.go index 785386c0..f2a467a2 100644 --- a/modules/net_recon.go +++ b/modules/net_recon.go @@ -1,11 +1,11 @@ package modules import ( - "fmt" + "time" + "github.com/evilsocket/bettercap-ng/log" "github.com/evilsocket/bettercap-ng/net" "github.com/evilsocket/bettercap-ng/session" - "time" ) type Discovery struct { @@ -108,35 +108,41 @@ func (d *Discovery) runDiff() { } } +func (d *Discovery) Configure() error { + return nil +} + func (d *Discovery) Start() error { - if d.Running() == false { - d.SetRunning(true) - - go func() { - for { - select { - case <-time.After(time.Duration(d.refresh) * time.Second): - var err error - - if d.current, err = net.ArpUpdate(d.Session.Interface.Name()); err != nil { - log.Error("%s", err) - continue - } - - d.runDiff() - - d.before = d.current - - case <-d.quit: - return - } - } - }() - - return nil - } else { - return fmt.Errorf("Network discovery already started.") + if d.Running() == true { + return session.ErrAlreadyStarted + } else if err := d.Configure(); err != nil { + return err } + + d.SetRunning(true) + + go func() { + for { + select { + case <-time.After(time.Duration(d.refresh) * time.Second): + var err error + + if d.current, err = net.ArpUpdate(d.Session.Interface.Name()); err != nil { + log.Error("%s", err) + continue + } + + d.runDiff() + + d.before = d.current + + case <-d.quit: + return + } + } + }() + + return nil } func (d *Discovery) Show() error { @@ -145,11 +151,10 @@ func (d *Discovery) Show() error { } func (d *Discovery) Stop() error { - if d.Running() == true { - d.SetRunning(false) - d.quit <- true - return nil - } else { - return fmt.Errorf("Network discovery already stopped.") + if d.Running() == false { + return session.ErrAlreadyStopped } + d.quit <- true + d.SetRunning(false) + return nil } diff --git a/modules/net_sniff.go b/modules/net_sniff.go index 096ae05c..b3e2f412 100644 --- a/modules/net_sniff.go +++ b/modules/net_sniff.go @@ -117,69 +117,74 @@ func (s *Sniffer) onPacketMatched(pkt gopacket.Packet) { } } -func (s *Sniffer) Start() error { - if s.Running() == false { - var err error +func (s *Sniffer) Configure() error { + var err error - if err, s.Ctx = s.GetContext(); err != nil { - if s.Ctx != nil { - s.Ctx.Close() - s.Ctx = nil - } - return err + if err, s.Ctx = s.GetContext(); err != nil { + if s.Ctx != nil { + s.Ctx.Close() + s.Ctx = nil } + return err + } + return nil +} + +func (s *Sniffer) Start() error { + if s.Running() == true { + return session.ErrAlreadyStarted + } else if err := s.Configure(); err != nil { + return err + } + + s.SetRunning(true) + + go func() { s.Stats = NewSnifferStats() - s.SetRunning(true) + defer s.Ctx.Close() - go func() { - defer s.Ctx.Close() + src := gopacket.NewPacketSource(s.Ctx.Handle, s.Ctx.Handle.LinkType()) + for packet := range src.Packets() { + if s.Running() == false { + break + } - src := gopacket.NewPacketSource(s.Ctx.Handle, s.Ctx.Handle.LinkType()) - for packet := range src.Packets() { - if s.Running() == false { - break - } + now := time.Now() + if s.Stats.FirstPacket.IsZero() { + s.Stats.FirstPacket = now + } + s.Stats.LastPacket = now - now := time.Now() - if s.Stats.FirstPacket.IsZero() { - s.Stats.FirstPacket = now - } - s.Stats.LastPacket = now + is_local := false + if s.isLocalPacket(packet) { + is_local = true + s.Stats.NumLocal++ + } - is_local := false - if s.isLocalPacket(packet) { - is_local = true - s.Stats.NumLocal++ - } + if s.Ctx.DumpLocal == true || is_local == false { + data := packet.Data() + if s.Ctx.Compiled == nil || s.Ctx.Compiled.Match(data) == true { + s.Stats.NumMatched++ - if s.Ctx.DumpLocal == true || is_local == false { - data := packet.Data() - if s.Ctx.Compiled == nil || s.Ctx.Compiled.Match(data) == true { - s.Stats.NumMatched++ + s.onPacketMatched(packet) - s.onPacketMatched(packet) - - if s.Ctx.OutputWriter != nil { - s.Ctx.OutputWriter.WritePacket(packet.Metadata().CaptureInfo, data) - s.Stats.NumWrote++ - } + if s.Ctx.OutputWriter != nil { + s.Ctx.OutputWriter.WritePacket(packet.Metadata().CaptureInfo, data) + s.Stats.NumWrote++ } } } - }() + } + }() - return nil - } else { - return fmt.Errorf("Network sniffer already started.") - } + return nil } func (s *Sniffer) Stop() error { - if s.Running() == true { - s.SetRunning(false) - return nil - } else { - return fmt.Errorf("Network sniffer already stopped.") + if s.Running() == false { + return session.ErrAlreadyStopped } + s.SetRunning(false) + return nil } diff --git a/session/session.go b/session/session.go index 7a9919a8..6a1acd4c 100644 --- a/session/session.go +++ b/session/session.go @@ -2,6 +2,7 @@ package session import ( "bufio" + "errors" "fmt" "os" "os/signal" @@ -20,6 +21,9 @@ import ( var ( I = (*Session)(nil) + + ErrAlreadyStarted = errors.New("Module is already running.") + ErrAlreadyStopped = errors.New("Module is not running.") ) type Session struct { diff --git a/session/session_core_handlers.go b/session/session_core_handlers.go index 37c81a69..806ac52e 100644 --- a/session/session_core_handlers.go +++ b/session/session_core_handlers.go @@ -89,6 +89,10 @@ func (s *Session) activeHandler(args []string, sess *Session) error { } func (s *Session) exitHandler(args []string, sess *Session) error { + for _, mod := range s.Modules { + mod.Stop() + } + s.Active = false s.Input.Close() return nil