mirror of
https://github.com/bettercap/bettercap
synced 2025-07-16 10:03:39 -07:00
new: centralized pcap capture configuration management
This commit is contained in:
parent
d0ecfd499f
commit
59dce4ced6
8 changed files with 118 additions and 62 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
"github.com/bettercap/bettercap/packets"
|
"github.com/bettercap/bettercap/packets"
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ func (mod *DHCP6Spoofer) Configure() error {
|
||||||
return session.ErrAlreadyStarted(mod.Name())
|
return session.ErrAlreadyStarted(mod.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
if mod.Handle, err = pcap.OpenLive(mod.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil {
|
if mod.Handle, err = network.Capture(mod.Session.Interface.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/log"
|
"github.com/bettercap/bettercap/log"
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
"github.com/bettercap/bettercap/packets"
|
"github.com/bettercap/bettercap/packets"
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ func (mod *DNSSpoofer) Configure() error {
|
||||||
|
|
||||||
if mod.Running() {
|
if mod.Running() {
|
||||||
return session.ErrAlreadyStarted(mod.Name())
|
return session.ErrAlreadyStarted(mod.Name())
|
||||||
} else if mod.Handle, err = pcap.OpenLive(mod.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil {
|
} else if mod.Handle, err = network.Capture(mod.Session.Interface.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err = mod.Handle.SetBPFFilter("udp"); err != nil {
|
} else if err = mod.Handle.SetBPFFilter("udp"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -5,12 +5,13 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/log"
|
"github.com/bettercap/bettercap/log"
|
||||||
"github.com/bettercap/bettercap/session"
|
|
||||||
"github.com/bettercap/bettercap/modules/dns_spoof"
|
"github.com/bettercap/bettercap/modules/dns_spoof"
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
"github.com/elazarl/goproxy"
|
"github.com/elazarl/goproxy"
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
|
@ -23,9 +24,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
httpsLinksParser = regexp.MustCompile(`https://[^"'/]+`)
|
httpsLinksParser = regexp.MustCompile(`https://[^"'/]+`)
|
||||||
domainCookieParser = regexp.MustCompile(`; ?(?i)domain=.*(;|$)`)
|
domainCookieParser = regexp.MustCompile(`; ?(?i)domain=.*(;|$)`)
|
||||||
flagsCookieParser = regexp.MustCompile(`; ?(?i)(secure|httponly)`)
|
flagsCookieParser = regexp.MustCompile(`; ?(?i)(secure|httponly)`)
|
||||||
)
|
)
|
||||||
|
|
||||||
type SSLStripper struct {
|
type SSLStripper struct {
|
||||||
|
@ -83,7 +84,7 @@ func (s *SSLStripper) Enable(enabled bool) {
|
||||||
if enabled && s.handle == nil {
|
if enabled && s.handle == nil {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if s.handle, err = pcap.OpenLive(s.session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil {
|
if s.handle, err = network.Capture(s.session.Interface.Name()); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +169,7 @@ func (s *SSLStripper) fixCookies(res *http.Response) {
|
||||||
origDomain := origParts[len(origParts)-2] + "." + origParts[len(origParts)-1]
|
origDomain := origParts[len(origParts)-2] + "." + origParts[len(origParts)-1]
|
||||||
strippedDomain := strippedParts[len(strippedParts)-2] + "." + strippedParts[len(strippedParts)-1]
|
strippedDomain := strippedParts[len(strippedParts)-2] + "." + strippedParts[len(strippedParts)-1]
|
||||||
|
|
||||||
log.Info("[%s] Fixing cookies on %s", tui.Green("sslstrip"),tui.Bold(strippedHost.Hostname))
|
log.Info("[%s] Fixing cookies on %s", tui.Green("sslstrip"), tui.Bold(strippedHost.Hostname))
|
||||||
cookies := make([]string, len(res.Header["Set-Cookie"]))
|
cookies := make([]string, len(res.Header["Set-Cookie"]))
|
||||||
// replace domain and strip "secure" flag for each cookie
|
// replace domain and strip "secure" flag for each cookie
|
||||||
for i, cookie := range res.Header["Set-Cookie"] {
|
for i, cookie := range res.Header["Set-Cookie"] {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/log"
|
"github.com/bettercap/bettercap/log"
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
"github.com/google/gopacket/pcap"
|
"github.com/google/gopacket/pcap"
|
||||||
|
@ -42,7 +43,7 @@ func (mod *Sniffer) GetContext() (error, *SnifferContext) {
|
||||||
* could hang waiting for a timeout to expire ...
|
* could hang waiting for a timeout to expire ...
|
||||||
*/
|
*/
|
||||||
readTimeout := 500 * time.Millisecond
|
readTimeout := 500 * time.Millisecond
|
||||||
if ctx.Handle, err = pcap.OpenLive(mod.Session.Interface.Name(), 65536, true, readTimeout); err != nil {
|
if ctx.Handle, err = network.CaptureWithTimeout(mod.Session.Interface.Name(), readTimeout); err != nil {
|
||||||
return err, ctx
|
return err, ctx
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
"github.com/bettercap/bettercap/packets"
|
"github.com/bettercap/bettercap/packets"
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
|
@ -115,7 +116,7 @@ func (mod *SynScanner) Configure() (err error) {
|
||||||
return session.ErrAlreadyStarted(mod.Name())
|
return session.ErrAlreadyStarted(mod.Name())
|
||||||
}
|
}
|
||||||
if mod.handle == nil {
|
if mod.handle == nil {
|
||||||
if mod.handle, err = pcap.OpenLive(mod.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil {
|
if mod.handle, err = network.Capture(mod.Session.Interface.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err = mod.handle.SetBPFFilter(fmt.Sprintf("tcp dst port %d", synSourcePort)); err != nil {
|
} else if err = mod.handle.SetBPFFilter(fmt.Sprintf("tcp dst port %d", synSourcePort)); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -91,7 +91,7 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
|
||||||
assocOpen: false,
|
assocOpen: false,
|
||||||
assocAcquired: false,
|
assocAcquired: false,
|
||||||
csaSilent: false,
|
csaSilent: false,
|
||||||
fakeAuthSilent: false,
|
fakeAuthSilent: false,
|
||||||
showManuf: false,
|
showManuf: false,
|
||||||
shakesAggregate: true,
|
shakesAggregate: true,
|
||||||
writes: &sync.WaitGroup{},
|
writes: &sync.WaitGroup{},
|
||||||
|
@ -226,11 +226,11 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
channel,_:=strconv.Atoi( args[1])
|
channel, _ := strconv.Atoi(args[1])
|
||||||
if channel>180 || channel<1{
|
if channel > 180 || channel < 1 {
|
||||||
return fmt.Errorf("%d is not a valid channel number",channel)
|
return fmt.Errorf("%d is not a valid channel number", channel)
|
||||||
}
|
}
|
||||||
return mod.startCSA(bssid,int8(channel))
|
return mod.startCSA(bssid, int8(channel))
|
||||||
})
|
})
|
||||||
|
|
||||||
channelSwitchAnnounce.Complete("wifi.channel_switch_announce", s.WiFiCompleterFull)
|
channelSwitchAnnounce.Complete("wifi.channel_switch_announce", s.WiFiCompleterFull)
|
||||||
|
@ -244,11 +244,11 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
client,err:=net.ParseMAC(args[1])
|
client, err := net.ParseMAC(args[1])
|
||||||
if err!=nil{
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return mod.startFakeAuth(bssid,client)
|
return mod.startFakeAuth(bssid, client)
|
||||||
})
|
})
|
||||||
|
|
||||||
fakeAuth.Complete("wifi.fake_auth", s.WiFiCompleterFull)
|
fakeAuth.Complete("wifi.fake_auth", s.WiFiCompleterFull)
|
||||||
|
@ -556,53 +556,33 @@ func (mod *WiFiModule) Configure() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setRFMonMaybeFatal := false
|
/*
|
||||||
|
* We don't want to pcap.BlockForever otherwise pcap_close(handle)
|
||||||
|
* could hang waiting for a timeout to expire ...
|
||||||
|
*/
|
||||||
|
opts := network.CAPTURE_DEFAULTS
|
||||||
|
opts.Timeout = 500 * time.Millisecond
|
||||||
|
opts.Monitor = true
|
||||||
|
|
||||||
for retry := 0; ; retry++ {
|
for retry := 0; ; retry++ {
|
||||||
ihandle, err := pcap.NewInactiveHandle(ifName)
|
if mod.handle, err = network.CaptureWithOptions(ifName, opts); err == nil {
|
||||||
if err != nil {
|
// we're done
|
||||||
return fmt.Errorf("error while opening interface %s: %s", ifName, err)
|
break
|
||||||
}
|
} else if retry == 0 /* && err.Error() == ErrIfaceNotUp */ {
|
||||||
defer ihandle.CleanUp()
|
// try to bring interface up and try again
|
||||||
|
mod.Info("interface %s is down, bringing it up ...", ifName)
|
||||||
/*
|
if err := network.ActivateInterface(ifName); err != nil {
|
||||||
* Calling SetRFMon is fatal when the interface is already in monitor mode.
|
return err
|
||||||
* gopacket has no GetRFMon analogue to SetRFMon with which we could check this, however ...
|
|
||||||
*/
|
|
||||||
if !setRFMonMaybeFatal {
|
|
||||||
if err = ihandle.SetRFMon(true); err != nil {
|
|
||||||
return fmt.Errorf("error while setting interface %s in monitor mode: %s", tui.Bold(ifName), err)
|
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
} else if !opts.Monitor {
|
||||||
|
// second fatal error, just bail
|
||||||
|
return fmt.Errorf("error while activating handle: %s", err)
|
||||||
} else {
|
} else {
|
||||||
mod.Debug("SetRFMon on interface %s might be fatal, skipping this time", tui.Bold(ifName))
|
// first fatal error, try again without setting the interface in monitor mode
|
||||||
|
mod.Warning("error while activating handle: %s, %s", err, tui.Bold("interface might already be monitoring. retrying!"))
|
||||||
|
opts.Monitor = false
|
||||||
}
|
}
|
||||||
if err = ihandle.SetSnapLen(65536); err != nil {
|
|
||||||
return fmt.Errorf("error while settng snapshot length: %s", err)
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* We don't want to pcap.BlockForever otherwise pcap_close(handle)
|
|
||||||
* could hang waiting for a timeout to expire ...
|
|
||||||
*/
|
|
||||||
readTimeout := 500 * time.Millisecond
|
|
||||||
if err = ihandle.SetTimeout(readTimeout); err != nil {
|
|
||||||
return fmt.Errorf("error while setting timeout: %s", err)
|
|
||||||
} else if mod.handle, err = ihandle.Activate(); err != nil {
|
|
||||||
if retry == 0 && err.Error() == ErrIfaceNotUp {
|
|
||||||
mod.Debug("interface %s is down, bringing it up ...", ifName)
|
|
||||||
if err := network.ActivateInterface(ifName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if setRFMonMaybeFatal {
|
|
||||||
return fmt.Errorf("error while activating handle: %s", err)
|
|
||||||
} else {
|
|
||||||
mod.Warning("error while activating handle: %s, %s", err, tui.Bold("interface might already be monitoring. retrying!"))
|
|
||||||
setRFMonMaybeFatal = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
71
network/pcap.go
Normal file
71
network/pcap.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/tui"
|
||||||
|
"github.com/google/gopacket/pcap"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PCAP_DEFAULT_SETRF = false
|
||||||
|
PCAP_DEFAULT_SNAPLEN = 65536
|
||||||
|
PCAP_DEFAULT_BUFSIZE = 2_097_152
|
||||||
|
PCAP_DEFAULT_PROMISC = true
|
||||||
|
PCAP_DEFAULT_TIMEOUT = pcap.BlockForever
|
||||||
|
)
|
||||||
|
|
||||||
|
var CAPTURE_DEFAULTS = CaptureOptions{
|
||||||
|
Monitor: PCAP_DEFAULT_SETRF,
|
||||||
|
Snaplen: PCAP_DEFAULT_SNAPLEN,
|
||||||
|
Bufsize: PCAP_DEFAULT_BUFSIZE,
|
||||||
|
Promisc: PCAP_DEFAULT_PROMISC,
|
||||||
|
Timeout: PCAP_DEFAULT_TIMEOUT,
|
||||||
|
}
|
||||||
|
|
||||||
|
type CaptureOptions struct {
|
||||||
|
Monitor bool
|
||||||
|
Snaplen int
|
||||||
|
Bufsize int
|
||||||
|
Promisc bool
|
||||||
|
Timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func CaptureWithOptions(ifName string, options CaptureOptions) (*pcap.Handle, error) {
|
||||||
|
Debug("creating capture for '%s' with options: %+v", ifName, options)
|
||||||
|
|
||||||
|
ihandle, err := pcap.NewInactiveHandle(ifName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error while opening interface %s: %s", ifName, err)
|
||||||
|
}
|
||||||
|
defer ihandle.CleanUp()
|
||||||
|
|
||||||
|
if options.Monitor {
|
||||||
|
if err = ihandle.SetRFMon(true); err != nil {
|
||||||
|
return nil, fmt.Errorf("error while setting interface %s in monitor mode: %s", tui.Bold(ifName), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = ihandle.SetSnapLen(options.Snaplen); err != nil {
|
||||||
|
return nil, fmt.Errorf("error while settng snapshot length: %s", err)
|
||||||
|
} else if err = ihandle.SetBufferSize(options.Bufsize); err != nil {
|
||||||
|
return nil, fmt.Errorf("error while settng buffer size: %s", err)
|
||||||
|
} else if err = ihandle.SetPromisc(options.Promisc); err != nil {
|
||||||
|
return nil, fmt.Errorf("error while settng promiscuous mode to %v: %s", options.Promisc, err)
|
||||||
|
} else if err = ihandle.SetTimeout(options.Timeout); err != nil {
|
||||||
|
return nil, fmt.Errorf("error while settng snapshot length: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ihandle.Activate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Capture(ifName string) (*pcap.Handle, error) {
|
||||||
|
return CaptureWithOptions(ifName, CAPTURE_DEFAULTS)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CaptureWithTimeout(ifName string, timeout time.Duration) (*pcap.Handle, error) {
|
||||||
|
var opts = CAPTURE_DEFAULTS
|
||||||
|
opts.Timeout = timeout
|
||||||
|
return CaptureWithOptions(ifName, opts)
|
||||||
|
}
|
|
@ -69,7 +69,7 @@ func NewQueue(iface *network.Endpoint) (q *Queue, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if q.active {
|
if q.active {
|
||||||
if q.handle, err = pcap.OpenLive(iface.Name(), 1024, true, pcap.BlockForever); err != nil {
|
if q.handle, err = network.Capture(iface.Name()); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue