refact: some refactoring to proxy modules

This commit is contained in:
evilsocket 2018-01-11 19:53:14 +01:00
parent 195650777f
commit 291e87de39
11 changed files with 332 additions and 315 deletions

View file

@ -118,7 +118,7 @@ function dumpRaw(req) {
} }
function onRequest(req, res) { 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); dumpHeaders(req);

View file

@ -145,33 +145,30 @@ func (api *RestAPI) Configure() error {
} }
func (api *RestAPI) Start() 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 return err
} }
if api.Running() == false { api.SetRunning(true)
api.SetRunning(true) go func() {
go func() { log.Info("API server starting on https://%s", api.server.Addr)
log.Info("API server starting on https://%s", api.server.Addr) err := api.server.ListenAndServeTLS(api.certFile, api.keyFile)
err := api.server.ListenAndServeTLS(api.certFile, api.keyFile) if err != nil && err != http.ErrServerClosed {
if err != nil && err != http.ErrServerClosed { panic(err)
panic(err) }
} }()
}()
return nil return nil
}
return fmt.Errorf("REST API server already started.")
} }
func (api *RestAPI) Stop() error { func (api *RestAPI) Stop() error {
if api.Running() == true { if api.Running() == false {
api.SetRunning(false) return session.ErrAlreadyStopped
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.")
} }
api.SetRunning(false)
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
return api.server.Shutdown(ctx)
} }

View file

@ -15,13 +15,15 @@ import (
type ArpSpoofer struct { type ArpSpoofer struct {
session.SessionModule session.SessionModule
done chan bool done chan bool
addresses []net.IP
} }
func NewArpSpoofer(s *session.Session) *ArpSpoofer { func NewArpSpoofer(s *session.Session) *ArpSpoofer {
p := &ArpSpoofer{ p := &ArpSpoofer{
SessionModule: session.NewSessionModule("arp.spoof", s), SessionModule: session.NewSessionModule("arp.spoof", s),
done: make(chan bool), done: make(chan bool),
addresses: make([]net.IP, 0),
} }
p.AddParam(session.NewStringParameter("arp.spoof.targets", session.ParamSubnet, "", "IP addresses to spoof.")) 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 return hw, nil
} }
func (p *ArpSpoofer) sendArp(addresses []net.IP, saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) { func (p *ArpSpoofer) sendArp(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) {
for _, ip := range addresses { for _, ip := range p.addresses {
if p.shouldSpoof(ip) == false { if p.shouldSpoof(ip) == false {
log.Debug("Skipping address %s from ARP spoofing.", ip) log.Debug("Skipping address %s from ARP spoofing.", ip)
continue continue
@ -127,80 +129,69 @@ func (p *ArpSpoofer) sendArp(addresses []net.IP, saddr net.IP, smac net.Hardware
} }
func (p *ArpSpoofer) unSpoof() error { 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 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 return err
} else {
targets = v.(string)
} }
list, err := iprange.Parse(targets) list, err := iprange.Parse(targets)
if err != nil { if err != nil {
return fmt.Errorf("Error while parsing arp.spoof.targets variable '%s': %s.", targets, err) return fmt.Errorf("Error while parsing arp.spoof.targets variable '%s': %s.", targets, err)
} }
addresses := list.Expand() p.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)
return nil return nil
} }
func (p *ArpSpoofer) Start() error { func (p *ArpSpoofer) Start() error {
if p.Running() == false { if p.Running() == true {
var err error return session.ErrAlreadyStarted
var targets string } else if err := p.Configure(); err != nil {
return err
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.")
} }
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 { func (p *ArpSpoofer) Stop() error {
if p.Running() == true { if p.Running() == false {
p.SetRunning(false) return session.ErrAlreadyStopped
log.Info("Waiting for ARP spoofer to stop ...")
<-p.done
p.unSpoof()
return nil
} else {
return fmt.Errorf("ARP spoofer already stopped.")
} }
log.Info("Waiting for ARP spoofer to stop ...")
p.SetRunning(false)
<-p.done
p.unSpoof()
return nil
} }

View file

@ -10,12 +10,14 @@ import (
type EventsStream struct { type EventsStream struct {
session.SessionModule session.SessionModule
quit chan bool filter string
quit chan bool
} }
func NewEventsStream(s *session.Session) *EventsStream { func NewEventsStream(s *session.Session) *EventsStream {
stream := &EventsStream{ stream := &EventsStream{
SessionModule: session.NewSessionModule("events.stream", s), SessionModule: session.NewSessionModule("events.stream", s),
filter: "",
quit: make(chan bool), quit: make(chan bool),
} }
@ -58,52 +60,55 @@ func (s EventsStream) Author() string {
return "Simone Margaritelli <evilsocket@protonmail.com>" return "Simone Margaritelli <evilsocket@protonmail.com>"
} }
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 { func (s *EventsStream) Start() error {
if s.Running() == false { if s.Running() == true {
var err error return session.ErrAlreadyStarted
var filter string } else if err := s.Configure(); err != nil {
return err
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
} }
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 { func (s *EventsStream) Stop() error {
if s.Running() == true { if s.Running() == false {
s.SetRunning(false) return session.ErrAlreadyStopped
s.quit <- true
return nil
} }
return fmt.Errorf("Events stream already stopped.") s.SetRunning(false)
s.quit <- true
return nil
} }

View file

@ -116,6 +116,28 @@ func NewHttpProxy(s *session.Session) *HttpProxy {
return p 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 { func (p *HttpProxy) Name() string {
return "http.proxy" return "http.proxy"
} }
@ -128,16 +150,12 @@ func (p *HttpProxy) Author() string {
return "Simone Margaritelli <evilsocket@protonmail.com>" return "Simone Margaritelli <evilsocket@protonmail.com>"
} }
func (p *HttpProxy) Start() error { func (p *HttpProxy) Configure() error {
var err error var err error
var http_port int var http_port int
var proxy_port int var proxy_port int
var scriptPath string 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 { if err, p.address = p.StringParam("http.proxy.address"); err != nil {
return err 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 { if p.Session.Firewall.IsForwardingEnabled() == false {
log.Info("Enabling forwarding.") log.Info("Enabling forwarding.")
p.Session.Firewall.EnableForwarding(true) p.Session.Firewall.EnableForwarding(true)
@ -177,10 +197,18 @@ func (p *HttpProxy) Start() error {
log.Debug("Applied redirection %s", p.redirection.String()) log.Debug("Applied redirection %s", p.redirection.String())
address := fmt.Sprintf("%s:%d", p.address, proxy_port) return nil
p.server = http.Server{Addr: address, Handler: p.proxy} }
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() { go func() {
p.SetRunning(true)
if err := p.server.ListenAndServe(); err != nil { if err := p.server.ListenAndServe(); err != nil {
p.SetRunning(false) p.SetRunning(false)
log.Warning("%s", err) log.Warning("%s", err)
@ -191,42 +219,20 @@ func (p *HttpProxy) Start() error {
} }
func (p *HttpProxy) Stop() error { func (p *HttpProxy) Stop() error {
if p.Running() == true { if p.Running() == false {
p.SetRunning(false) return session.ErrAlreadyStopped
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) }
defer cancel() p.SetRunning(false)
p.server.Shutdown(ctx)
if p.redirection != nil { if p.redirection != nil {
log.Debug("Disabling redirection %s", p.redirection.String()) log.Debug("Disabling redirection %s", p.redirection.String())
if err := p.Session.Firewall.EnableRedirection(p.redirection, false); err != nil { if err := p.Session.Firewall.EnableRedirection(p.redirection, false); err != nil {
return err return err
}
p.redirection = nil
} }
return nil p.redirection = nil
} else {
return fmt.Errorf("HTTP proxy stopped.")
} }
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
func (p *HttpProxy) doProxy(req *http.Request) bool { defer cancel()
blacklist := []string{ return p.server.Shutdown(ctx)
"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
} }

View file

@ -88,33 +88,30 @@ func (httpd *HttpServer) Configure() error {
} }
func (httpd *HttpServer) Start() 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 return err
} }
if httpd.Running() == false { httpd.SetRunning(true)
httpd.SetRunning(true) go func() {
go func() { log.Info("httpd server starting on http://%s", httpd.server.Addr)
log.Info("httpd server starting on http://%s", httpd.server.Addr) err := httpd.server.ListenAndServe()
err := httpd.server.ListenAndServe() if err != nil && err != http.ErrServerClosed {
if err != nil && err != http.ErrServerClosed { panic(err)
panic(err) }
} }()
}()
return nil return nil
}
return fmt.Errorf("httpd server already started.")
} }
func (httpd *HttpServer) Stop() error { func (httpd *HttpServer) Stop() error {
if httpd.Running() == true { if httpd.Running() == false {
httpd.SetRunning(false) return session.ErrAlreadyStopped
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
return httpd.server.Shutdown(ctx)
} else {
return fmt.Errorf("httpd server already stopped.")
} }
httpd.SetRunning(false)
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
return httpd.server.Shutdown(ctx)
} }

View file

@ -13,6 +13,7 @@ import (
type Prober struct { type Prober struct {
session.SessionModule session.SessionModule
throttle int
} }
func NewProber(s *session.Session) *Prober { 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 { func (p *Prober) Configure() error {
if p.Running() == false { var err error
var err error if err, p.throttle = p.IntParam("net.probe.throttle"); err != nil {
var throttle int return err
} else {
log.Debug("Throttling packets of %d ms.", p.throttle)
}
return nil
}
if err, throttle = p.IntParam("net.probe.throttle"); err != nil { func (p *Prober) Start() error {
return err if p.Running() == true {
} else { return session.ErrAlreadyStarted
log.Debug("Throttling packets of %d ms.", throttle) } 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() { for p.Running() {
list, err := iprange.Parse(p.Session.Interface.CIDR()) for _, ip := range addresses {
if err != nil { if p.shouldProbe(ip) == false {
log.Fatal("%s", err) log.Debug("Skipping address %s from UDP probing.", ip)
} continue
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)
}
} }
time.Sleep(5 * time.Second) p.sendProbe(from, from_hw, ip)
}
}()
return nil if p.throttle > 0 {
} else { time.Sleep(time.Duration(p.throttle) * time.Millisecond)
return fmt.Errorf("Network prober already started.") }
} }
time.Sleep(5 * time.Second)
}
}()
return nil
} }
func (p *Prober) Stop() error { func (p *Prober) Stop() error {
if p.Running() == true { if p.Running() == false {
p.SetRunning(false) return session.ErrAlreadyStopped
return nil
} else {
return fmt.Errorf("Network prober already stopped.")
} }
p.SetRunning(false)
return nil
} }

View file

@ -1,11 +1,11 @@
package modules package modules
import ( import (
"fmt" "time"
"github.com/evilsocket/bettercap-ng/log" "github.com/evilsocket/bettercap-ng/log"
"github.com/evilsocket/bettercap-ng/net" "github.com/evilsocket/bettercap-ng/net"
"github.com/evilsocket/bettercap-ng/session" "github.com/evilsocket/bettercap-ng/session"
"time"
) )
type Discovery struct { type Discovery struct {
@ -108,35 +108,41 @@ func (d *Discovery) runDiff() {
} }
} }
func (d *Discovery) Configure() error {
return nil
}
func (d *Discovery) Start() error { func (d *Discovery) Start() error {
if d.Running() == false { if d.Running() == true {
d.SetRunning(true) return session.ErrAlreadyStarted
} else if err := d.Configure(); err != nil {
go func() { return err
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.")
} }
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 { func (d *Discovery) Show() error {
@ -145,11 +151,10 @@ func (d *Discovery) Show() error {
} }
func (d *Discovery) Stop() error { func (d *Discovery) Stop() error {
if d.Running() == true { if d.Running() == false {
d.SetRunning(false) return session.ErrAlreadyStopped
d.quit <- true
return nil
} else {
return fmt.Errorf("Network discovery already stopped.")
} }
d.quit <- true
d.SetRunning(false)
return nil
} }

View file

@ -117,69 +117,74 @@ func (s *Sniffer) onPacketMatched(pkt gopacket.Packet) {
} }
} }
func (s *Sniffer) Start() error { func (s *Sniffer) Configure() error {
if s.Running() == false { var err error
var err error
if err, s.Ctx = s.GetContext(); err != nil { if err, s.Ctx = s.GetContext(); err != nil {
if s.Ctx != nil { if s.Ctx != nil {
s.Ctx.Close() s.Ctx.Close()
s.Ctx = nil s.Ctx = nil
}
return err
} }
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.Stats = NewSnifferStats()
s.SetRunning(true) defer s.Ctx.Close()
go func() { src := gopacket.NewPacketSource(s.Ctx.Handle, s.Ctx.Handle.LinkType())
defer s.Ctx.Close() for packet := range src.Packets() {
if s.Running() == false {
break
}
src := gopacket.NewPacketSource(s.Ctx.Handle, s.Ctx.Handle.LinkType()) now := time.Now()
for packet := range src.Packets() { if s.Stats.FirstPacket.IsZero() {
if s.Running() == false { s.Stats.FirstPacket = now
break }
} s.Stats.LastPacket = now
now := time.Now() is_local := false
if s.Stats.FirstPacket.IsZero() { if s.isLocalPacket(packet) {
s.Stats.FirstPacket = now is_local = true
} s.Stats.NumLocal++
s.Stats.LastPacket = now }
is_local := false if s.Ctx.DumpLocal == true || is_local == false {
if s.isLocalPacket(packet) { data := packet.Data()
is_local = true if s.Ctx.Compiled == nil || s.Ctx.Compiled.Match(data) == true {
s.Stats.NumLocal++ s.Stats.NumMatched++
}
if s.Ctx.DumpLocal == true || is_local == false { s.onPacketMatched(packet)
data := packet.Data()
if s.Ctx.Compiled == nil || s.Ctx.Compiled.Match(data) == true {
s.Stats.NumMatched++
s.onPacketMatched(packet) if s.Ctx.OutputWriter != nil {
s.Ctx.OutputWriter.WritePacket(packet.Metadata().CaptureInfo, data)
if s.Ctx.OutputWriter != nil { s.Stats.NumWrote++
s.Ctx.OutputWriter.WritePacket(packet.Metadata().CaptureInfo, data)
s.Stats.NumWrote++
}
} }
} }
} }
}() }
}()
return nil return nil
} else {
return fmt.Errorf("Network sniffer already started.")
}
} }
func (s *Sniffer) Stop() error { func (s *Sniffer) Stop() error {
if s.Running() == true { if s.Running() == false {
s.SetRunning(false) return session.ErrAlreadyStopped
return nil
} else {
return fmt.Errorf("Network sniffer already stopped.")
} }
s.SetRunning(false)
return nil
} }

View file

@ -2,6 +2,7 @@ package session
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"os" "os"
"os/signal" "os/signal"
@ -20,6 +21,9 @@ import (
var ( var (
I = (*Session)(nil) I = (*Session)(nil)
ErrAlreadyStarted = errors.New("Module is already running.")
ErrAlreadyStopped = errors.New("Module is not running.")
) )
type Session struct { type Session struct {

View file

@ -89,6 +89,10 @@ func (s *Session) activeHandler(args []string, sess *Session) error {
} }
func (s *Session) exitHandler(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.Active = false
s.Input.Close() s.Input.Close()
return nil return nil