Skip to content

Commit

Permalink
new: centralized pcap capture configuration management
Browse files Browse the repository at this point in the history
  • Loading branch information
evilsocket committed Aug 21, 2021
1 parent d0ecfd4 commit 59dce4c
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 62 deletions.
3 changes: 2 additions & 1 deletion modules/dhcp6_spoof/dhcp6_spoof.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"
"time"

"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/packets"
"github.com/bettercap/bettercap/session"

Expand Down Expand Up @@ -83,7 +84,7 @@ func (mod *DHCP6Spoofer) Configure() error {
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
}

Expand Down
3 changes: 2 additions & 1 deletion modules/dns_spoof/dns_spoof.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sync"

"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/packets"
"github.com/bettercap/bettercap/session"

Expand Down Expand Up @@ -100,7 +101,7 @@ func (mod *DNSSpoofer) Configure() error {

if mod.Running() {
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
} else if err = mod.Handle.SetBPFFilter("udp"); err != nil {
return err
Expand Down
13 changes: 7 additions & 6 deletions modules/http_proxy/http_proxy_base_sslstriper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import (
"net/http"
"net/url"
"regexp"
"strings"
"strconv"
"strings"

"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/session"
"github.com/bettercap/bettercap/modules/dns_spoof"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/session"

"github.com/elazarl/goproxy"
"github.com/google/gopacket"
Expand All @@ -23,9 +24,9 @@ import (
)

var (
httpsLinksParser = regexp.MustCompile(`https://[^"'/]+`)
httpsLinksParser = regexp.MustCompile(`https://[^"'/]+`)
domainCookieParser = regexp.MustCompile(`; ?(?i)domain=.*(;|$)`)
flagsCookieParser = regexp.MustCompile(`; ?(?i)(secure|httponly)`)
flagsCookieParser = regexp.MustCompile(`; ?(?i)(secure|httponly)`)
)

type SSLStripper struct {
Expand Down Expand Up @@ -83,7 +84,7 @@ func (s *SSLStripper) Enable(enabled bool) {
if enabled && s.handle == nil {
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)
}

Expand Down Expand Up @@ -168,7 +169,7 @@ func (s *SSLStripper) fixCookies(res *http.Response) {
origDomain := origParts[len(origParts)-2] + "." + origParts[len(origParts)-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"]))
// replace domain and strip "secure" flag for each cookie
for i, cookie := range res.Header["Set-Cookie"] {
Expand Down
3 changes: 2 additions & 1 deletion modules/net_sniff/net_sniff_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/session"

"github.com/google/gopacket/pcap"
Expand Down Expand Up @@ -42,7 +43,7 @@ func (mod *Sniffer) GetContext() (error, *SnifferContext) {
* could hang waiting for a timeout to expire ...
*/
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
}
} else {
Expand Down
3 changes: 2 additions & 1 deletion modules/syn_scan/syn_scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync/atomic"
"time"

"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/packets"
"github.com/bettercap/bettercap/session"

Expand Down Expand Up @@ -115,7 +116,7 @@ func (mod *SynScanner) Configure() (err error) {
return session.ErrAlreadyStarted(mod.Name())
}
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
} else if err = mod.handle.SetBPFFilter(fmt.Sprintf("tcp dst port %d", synSourcePort)); err != nil {
return err
Expand Down
82 changes: 31 additions & 51 deletions modules/wifi/wifi.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
assocOpen: false,
assocAcquired: false,
csaSilent: false,
fakeAuthSilent: false,
fakeAuthSilent: false,
showManuf: false,
shakesAggregate: true,
writes: &sync.WaitGroup{},
Expand Down Expand Up @@ -226,11 +226,11 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
if err != nil {
return err
}
channel,_:=strconv.Atoi( args[1])
if channel>180 || channel<1{
return fmt.Errorf("%d is not a valid channel number",channel)
channel, _ := strconv.Atoi(args[1])
if channel > 180 || channel < 1 {
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)
Expand All @@ -244,11 +244,11 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
if err != nil {
return err
}
client,err:=net.ParseMAC(args[1])
if err!=nil{
client, err := net.ParseMAC(args[1])
if err != nil {
return err
}
return mod.startFakeAuth(bssid,client)
return mod.startFakeAuth(bssid, client)
})

fakeAuth.Complete("wifi.fake_auth", s.WiFiCompleterFull)
Expand Down Expand Up @@ -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++ {
ihandle, err := pcap.NewInactiveHandle(ifName)
if err != nil {
return fmt.Errorf("error while opening interface %s: %s", ifName, err)
}
defer ihandle.CleanUp()

/*
* Calling SetRFMon is fatal when the interface is already in monitor mode.
* 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)
if mod.handle, err = network.CaptureWithOptions(ifName, opts); err == nil {
// we're done
break
} else if retry == 0 /* && err.Error() == ErrIfaceNotUp */ {
// 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 {
return err
}
continue
} else if !opts.Monitor {
// second fatal error, just bail
return fmt.Errorf("error while activating handle: %s", err)
} else {
mod.Debug("SetRFMon on interface %s might be fatal, skipping this time", tui.Bold(ifName))
}
if err = ihandle.SetSnapLen(65536); err != nil {
return fmt.Errorf("error while settng snapshot length: %s", err)
// 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
}
/*
* 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
}
}

Expand Down
71 changes: 71 additions & 0 deletions network/pcap.go
Original file line number Diff line number Diff line change
@@ -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)
}
2 changes: 1 addition & 1 deletion packets/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func NewQueue(iface *network.Endpoint) (q *Queue, err error) {
}

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
}

Expand Down

0 comments on commit 59dce4c

Please sign in to comment.