mirror of
https://github.com/bettercap/bettercap
synced 2025-08-20 05:23:19 -07:00
Merge branch 'master' of github.com:evilsocket/bettercap-ng
This commit is contained in:
commit
8825ecb8db
25 changed files with 343 additions and 166 deletions
55
README.md
55
README.md
|
@ -278,6 +278,61 @@ function onResponse(req, res) {
|
|||
}
|
||||
```
|
||||
|
||||
#### caplets/airmon.cap
|
||||
|
||||
Put a wifi interface in monitor mode and listen for frames in order to detect WiF access points and clients.
|
||||
|
||||
```
|
||||
set $ {by}{fw}{env.iface.name}{reset} {bold}» {reset}
|
||||
set ticker.commands clear; wifi.show
|
||||
|
||||
# uncomment to disable channel hopping
|
||||
# set wifi.recon.channel 1
|
||||
|
||||
wifi.recon on
|
||||
ticker on
|
||||
events.clear
|
||||
clear
|
||||
```
|
||||
|
||||
#### caplets/wpa\_handshake.cap
|
||||
|
||||
Use various modules to inject wifi frames performing a deauthentication attack, while a sniffer is waiting for WPA handshakes.
|
||||
|
||||
```
|
||||
# swag prompt for wifi
|
||||
set $ {by}{fw}{env.iface.name}{reset} {bold}» {reset}
|
||||
|
||||
# Sniff EAPOL frames ( WPA handshakes ) and save them to a pcap file.
|
||||
set net.sniff.verbose true
|
||||
set net.sniff.filter ether proto 0x888e
|
||||
set net.sniff.output wpa.pcap
|
||||
net.sniff on
|
||||
|
||||
# since we need to capture the handshake, we can't hop
|
||||
# through channels but we need to stick to the one we're
|
||||
# interested in otherwise the sniffer might lose packets.
|
||||
set wifi.recon.channel 1
|
||||
|
||||
wifi.recon on
|
||||
|
||||
# uncomment to recon clients of a specific AP given its BSSID
|
||||
# wifi.recon DE:AD:BE:EF:DE:AD
|
||||
|
||||
events.clear
|
||||
clear
|
||||
|
||||
# now just deauth clients and wait ^_^
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# wifi.deauth AP-BSSID-HERE
|
||||
#
|
||||
# This will deauth every client for this specific access point,
|
||||
# you can put it as ticker.commands to have the ticker module
|
||||
# periodically deauth clients :D
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
`bettercap` and `bettercap-ng` are made with ♥ by [Simone Margaritelli](https://www.evilsocket.net/) and they're released under the GPL 3 license.
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
# let's add some api :D
|
||||
include caplets/rest-api.cap
|
||||
|
||||
set $ {by}{fw}{env.iface.name}{reset} {bold}» {reset}
|
||||
set ticker.commands clear; wifi.show
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@ net.sniff on
|
|||
# interested in otherwise the sniffer might lose packets.
|
||||
set wifi.recon.channel 1
|
||||
|
||||
# this will enable the wifi recon
|
||||
set ticker.commands clear; wifi.show
|
||||
wifi.recon on
|
||||
ticker on
|
||||
|
||||
# uncomment to recon clients of a specific AP given its BSSID
|
||||
# wifi.recon DE:AD:BE:EF:DE:AD
|
||||
|
@ -29,3 +32,7 @@ clear
|
|||
# This will deauth every client for this specific access point,
|
||||
# you can put it as ticker.commands to have the ticker module
|
||||
# periodically deauth clients :D
|
||||
#
|
||||
# For more options `help wifi.recon`.
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ type PfFirewall struct {
|
|||
iface *network.Endpoint
|
||||
filename string
|
||||
forwarding bool
|
||||
enabled bool
|
||||
}
|
||||
|
||||
func Make(iface *network.Endpoint) FirewallManager {
|
||||
|
@ -29,6 +30,7 @@ func Make(iface *network.Endpoint) FirewallManager {
|
|||
iface: iface,
|
||||
filename: pfFilePath,
|
||||
forwarding: false,
|
||||
enabled: false,
|
||||
}
|
||||
|
||||
firewall.forwarding = firewall.IsForwardingEnabled()
|
||||
|
@ -108,7 +110,8 @@ func (f PfFirewall) generateRule(r *Redirection) string {
|
|||
r.Interface, r.Protocol, src_a, r.SrcPort, dst_a, r.DstPort)
|
||||
}
|
||||
|
||||
func (f PfFirewall) enable(enabled bool) {
|
||||
func (f *PfFirewall) enable(enabled bool) {
|
||||
f.enabled = enabled
|
||||
if enabled {
|
||||
core.Exec("pfctl", []string{"-e"})
|
||||
} else {
|
||||
|
@ -165,11 +168,9 @@ func (f PfFirewall) EnableRedirection(r *Redirection, enabled bool) error {
|
|||
}
|
||||
|
||||
func (f PfFirewall) Restore() {
|
||||
err := f.EnableForwarding(f.forwarding)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s", err)
|
||||
f.EnableForwarding(f.forwarding)
|
||||
if f.enabled {
|
||||
f.enable(false)
|
||||
}
|
||||
|
||||
f.enable(false)
|
||||
os.Remove(f.filename)
|
||||
}
|
||||
|
|
|
@ -19,9 +19,6 @@ type APIResponse struct {
|
|||
|
||||
func SafeBind(c *gin.Context, obj interface{}) error {
|
||||
decoder := json.NewDecoder(io.LimitReader(c.Request.Body, 100*1024))
|
||||
if binding.EnableDecoderUseNumber {
|
||||
decoder.UseNumber()
|
||||
}
|
||||
if err := decoder.Decode(obj); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -154,8 +154,8 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet,
|
|||
}
|
||||
|
||||
var ip net.IP
|
||||
if t, found := s.Session.Lan.Hosts[target.String()]; found == true {
|
||||
ip = t.IP
|
||||
if h, found := s.Session.Lan.Get(target.String()); found == true {
|
||||
ip = h.IP
|
||||
} else {
|
||||
log.Warning("Address %s not known, using random identity association address.", target.String())
|
||||
rand.Read(ip)
|
||||
|
@ -312,8 +312,8 @@ func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.P
|
|||
addr = net.IP(raw[0])
|
||||
}
|
||||
|
||||
if t, found := s.Session.Lan.Hosts[target.String()]; found == true {
|
||||
log.Info("[%s] IPv6 address %s is now assigned to %s", core.Green("dhcp6"), addr.String(), t)
|
||||
if h, found := s.Session.Lan.Get(target.String()); found == true {
|
||||
log.Info("[%s] IPv6 address %s is now assigned to %s", core.Green("dhcp6"), addr.String(), h)
|
||||
} else {
|
||||
log.Info("[%s] IPv6 address %s is now assigned to %s", core.Green("dhcp6"), addr.String(), target)
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ func (s *DNSSpoofer) dnsReply(pkt gopacket.Packet, peth *layers.Ethernet, pudp *
|
|||
redir := fmt.Sprintf("(->%s)", s.Address)
|
||||
who := target.String()
|
||||
|
||||
if t, found := s.Session.Lan.Hosts[target.String()]; found == true {
|
||||
if t, found := s.Session.Lan.Get(target.String()); found == true {
|
||||
who = t.String()
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,33 @@ func (s EventsStream) viewLogEvent(e session.Event) {
|
|||
e.Data.(session.LogMessage).Message)
|
||||
}
|
||||
|
||||
func (s EventsStream) viewStationEvent(e session.Event) {
|
||||
st := e.Data.(*network.Station)
|
||||
vend := ""
|
||||
if st.Vendor != "" {
|
||||
vend = fmt.Sprintf(" (%s)", st.Vendor)
|
||||
}
|
||||
|
||||
if e.Tag == "wifi.station.new" {
|
||||
fmt.Printf("[%s] WiFi station %s detected as %s%s.\n",
|
||||
e.Time.Format(eventTimeFormat),
|
||||
core.Bold(st.ESSID()),
|
||||
core.Green(st.BSSID()),
|
||||
vend)
|
||||
} else if e.Tag == "wifi.station.lost" {
|
||||
fmt.Printf("[%s] WiFi station %s (%s) lost.\n",
|
||||
e.Time.Format(eventTimeFormat),
|
||||
core.Red(st.ESSID()),
|
||||
st.BSSID())
|
||||
} else {
|
||||
fmt.Printf("[%s] [%s] %s\n",
|
||||
e.Time.Format(eventTimeFormat),
|
||||
core.Green(e.Tag),
|
||||
st)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s EventsStream) viewEndpointEvent(e session.Event) {
|
||||
t := e.Data.(*network.Endpoint)
|
||||
vend := ""
|
||||
|
@ -74,6 +101,8 @@ func (s *EventsStream) View(e session.Event, refresh bool) {
|
|||
s.viewLogEvent(e)
|
||||
} else if strings.HasPrefix(e.Tag, "endpoint.") {
|
||||
s.viewEndpointEvent(e)
|
||||
} else if strings.HasPrefix(e.Tag, "wifi.station.") {
|
||||
s.viewStationEvent(e)
|
||||
} else if strings.HasPrefix(e.Tag, "mod.") {
|
||||
s.viewModuleEvent(e)
|
||||
} else if strings.HasPrefix(e.Tag, "net.sniff.") {
|
||||
|
|
|
@ -45,7 +45,7 @@ func LoadProxyScriptSource(path, source string, sess *session.Session) (err erro
|
|||
}
|
||||
|
||||
// define session pointer
|
||||
err = s.VM.Set("env", sess.Env.Storage)
|
||||
err = s.VM.Set("env", sess.Env.Data)
|
||||
if err != nil {
|
||||
log.Error("Error while defining environment: %s", err)
|
||||
return
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/evilsocket/bettercap-ng/log"
|
||||
"github.com/evilsocket/bettercap-ng/network"
|
||||
"github.com/evilsocket/bettercap-ng/session"
|
||||
|
||||
"github.com/malfunkt/iprange"
|
||||
|
@ -80,6 +81,11 @@ func (p *Prober) Start() error {
|
|||
}
|
||||
|
||||
return p.SetRunning(true, func() {
|
||||
if p.Session.Interface.IpAddress == network.MonitorModeAddress {
|
||||
log.Info("Interface is in monitor mode, skipping net.probe")
|
||||
return
|
||||
}
|
||||
|
||||
list, err := iprange.Parse(p.Session.Interface.CIDR())
|
||||
if err != nil {
|
||||
log.Fatal("%s", err)
|
||||
|
|
|
@ -71,11 +71,12 @@ func (d Discovery) Author() string {
|
|||
func (d *Discovery) runDiff(cache network.ArpTable) {
|
||||
// check for endpoints who disappeared
|
||||
var rem network.ArpTable = make(network.ArpTable)
|
||||
for mac, t := range d.Session.Lan.Hosts {
|
||||
|
||||
d.Session.Lan.EachHost(func(mac string, e *network.Endpoint) {
|
||||
if _, found := cache[mac]; found == false {
|
||||
rem[mac] = t.IpAddress
|
||||
rem[mac] = e.IpAddress
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
for mac, ip := range rem {
|
||||
d.Session.Lan.Remove(ip, mac)
|
||||
|
|
28
modules/net_sniff_dot11.go
Normal file
28
modules/net_sniff_dot11.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
)
|
||||
|
||||
func dot11Parser(radiotap *layers.RadioTap, dot11 *layers.Dot11, pkt gopacket.Packet, verbose bool) {
|
||||
NewSnifferEvent(
|
||||
pkt.Metadata().Timestamp,
|
||||
"802.11",
|
||||
"-",
|
||||
"-",
|
||||
SniffData{
|
||||
"Size": len(pkt.Data()),
|
||||
},
|
||||
"%s %s proto=%d a1=%s a2=%s a3=%s a4=%s seqn=%d frag=%d",
|
||||
dot11.Type,
|
||||
dot11.Flags,
|
||||
dot11.Proto,
|
||||
dot11.Address1,
|
||||
dot11.Address2,
|
||||
dot11.Address3,
|
||||
dot11.Address4,
|
||||
dot11.SequenceNumber,
|
||||
dot11.FragmentNumber,
|
||||
).Push()
|
||||
}
|
|
@ -86,22 +86,6 @@ func unkParser(ip *layers.IPv4, pkt gopacket.Packet, verbose bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func dot11Parser(radiotap *layers.RadioTap, dot11 *layers.Dot11, pkt gopacket.Packet, verbose bool) {
|
||||
if verbose == true {
|
||||
NewSnifferEvent(
|
||||
pkt.Metadata().Timestamp,
|
||||
"802.11",
|
||||
"-",
|
||||
"-",
|
||||
SniffData{
|
||||
"Size": len(pkt.Data()),
|
||||
},
|
||||
"%v",
|
||||
dot11,
|
||||
).Push()
|
||||
}
|
||||
}
|
||||
|
||||
func mainParser(pkt gopacket.Packet, verbose bool) bool {
|
||||
// simple networking sniffing mode?
|
||||
nlayer := pkt.NetworkLayer()
|
||||
|
|
|
@ -23,8 +23,7 @@ func vIP(ip net.IP) string {
|
|||
}
|
||||
|
||||
address := ip.String()
|
||||
host := session.I.Lan.Get(address)
|
||||
|
||||
host := session.I.Lan.GetByIp(address)
|
||||
if host != nil {
|
||||
if host.Hostname != "" {
|
||||
return host.Hostname
|
||||
|
|
|
@ -322,7 +322,7 @@ func (w *WiFiRecon) startDeauth(apMac net.HardwareAddr, clMac net.HardwareAddr)
|
|||
} else {
|
||||
log.Info("Deauthing clients from AP %s ...", apMac.String())
|
||||
// deauth every authenticated client
|
||||
for _, station := range w.Session.WiFi.Stations {
|
||||
for _, station := range w.Session.WiFi.List() {
|
||||
if station.IsAP == false {
|
||||
w.sendDeauthPacket(apMac, station.HW)
|
||||
}
|
||||
|
|
85
network/aliases.go
Normal file
85
network/aliases.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/evilsocket/bettercap-ng/core"
|
||||
)
|
||||
|
||||
var fileName, _ = core.ExpandPath("~/bettercap.aliases")
|
||||
|
||||
type Aliases struct {
|
||||
sync.Mutex
|
||||
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func LoadAliases() (err error, aliases *Aliases) {
|
||||
aliases = &Aliases{
|
||||
data: make(map[string]string),
|
||||
}
|
||||
|
||||
if core.Exists(fileName) {
|
||||
var file *os.File
|
||||
|
||||
file, err = os.Open(fileName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.SplitN(line, " ", 2)
|
||||
mac := core.Trim(parts[0])
|
||||
alias := core.Trim(parts[1])
|
||||
aliases.data[mac] = alias
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Aliases) saveUnlocked() error {
|
||||
data := ""
|
||||
for mac, alias := range a.data {
|
||||
data += fmt.Sprintf("%s %s\n", mac, alias)
|
||||
}
|
||||
return ioutil.WriteFile(fileName, []byte(data), 0644)
|
||||
}
|
||||
|
||||
func (a *Aliases) Save() error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
return a.saveUnlocked()
|
||||
}
|
||||
|
||||
func (a *Aliases) Get(mac string) string {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
if alias, found := a.data[mac]; found == true {
|
||||
return alias
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a *Aliases) Set(mac, alias string) error {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
|
||||
if alias != "" {
|
||||
a.data[mac] = alias
|
||||
} else {
|
||||
delete(a.data, mac)
|
||||
}
|
||||
|
||||
return a.saveUnlocked()
|
||||
}
|
169
network/lan.go
169
network/lan.go
|
@ -1,18 +1,13 @@
|
|||
package network
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/evilsocket/bettercap-ng/core"
|
||||
)
|
||||
|
||||
const LANDefaultTTL = 10
|
||||
const LANDefaultttl = 10
|
||||
const LANAliasesFile = "~/bettercap.aliases"
|
||||
|
||||
type EndpointNewCallback func(e *Endpoint)
|
||||
|
@ -21,36 +16,54 @@ type EndpointLostCallback func(e *Endpoint)
|
|||
type LAN struct {
|
||||
sync.Mutex
|
||||
|
||||
Interface *Endpoint
|
||||
Gateway *Endpoint
|
||||
Hosts map[string]*Endpoint
|
||||
TTL map[string]uint
|
||||
Aliases map[string]string
|
||||
|
||||
Hosts map[string]*Endpoint `json:"hosts"`
|
||||
iface *Endpoint
|
||||
gateway *Endpoint
|
||||
ttl map[string]uint
|
||||
aliases *Aliases
|
||||
newCb EndpointNewCallback
|
||||
lostCb EndpointLostCallback
|
||||
aliasesFileName string
|
||||
}
|
||||
|
||||
func NewLAN(iface, gateway *Endpoint, newcb EndpointNewCallback, lostcb EndpointLostCallback) *LAN {
|
||||
lan := &LAN{
|
||||
Interface: iface,
|
||||
Gateway: gateway,
|
||||
Hosts: make(map[string]*Endpoint),
|
||||
TTL: make(map[string]uint),
|
||||
Aliases: make(map[string]string),
|
||||
newCb: newcb,
|
||||
lostCb: lostcb,
|
||||
err, aliases := LoadAliases()
|
||||
if err != nil {
|
||||
fmt.Printf("%s\n", err)
|
||||
}
|
||||
|
||||
lan.aliasesFileName, _ = core.ExpandPath(LANAliasesFile)
|
||||
if core.Exists(lan.aliasesFileName) {
|
||||
if err := lan.loadAliases(); err != nil {
|
||||
fmt.Printf("%s\n", err)
|
||||
}
|
||||
return &LAN{
|
||||
iface: iface,
|
||||
gateway: gateway,
|
||||
Hosts: make(map[string]*Endpoint),
|
||||
ttl: make(map[string]uint),
|
||||
aliases: aliases,
|
||||
newCb: newcb,
|
||||
lostCb: lostcb,
|
||||
}
|
||||
}
|
||||
|
||||
return lan
|
||||
func (lan *LAN) SetAliasFor(mac, alias string) bool {
|
||||
lan.Lock()
|
||||
defer lan.Unlock()
|
||||
|
||||
mac = NormalizeMac(mac)
|
||||
if e, found := lan.Hosts[mac]; found {
|
||||
lan.aliases.Set(mac, alias)
|
||||
e.Alias = alias
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (lan *LAN) Get(mac string) (*Endpoint, bool) {
|
||||
lan.Lock()
|
||||
defer lan.Unlock()
|
||||
|
||||
if e, found := lan.Hosts[mac]; found == true {
|
||||
return e, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (lan *LAN) List() (list []*Endpoint) {
|
||||
|
@ -64,62 +77,16 @@ func (lan *LAN) List() (list []*Endpoint) {
|
|||
return
|
||||
}
|
||||
|
||||
func (lan *LAN) loadAliases() error {
|
||||
file, err := os.Open(lan.aliasesFileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.SplitN(line, " ", 2)
|
||||
mac := core.Trim(parts[0])
|
||||
alias := core.Trim(parts[1])
|
||||
lan.Aliases[mac] = alias
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lan *LAN) saveAliases() {
|
||||
data := ""
|
||||
for mac, alias := range lan.Aliases {
|
||||
data += fmt.Sprintf("%s %s\n", mac, alias)
|
||||
}
|
||||
ioutil.WriteFile(lan.aliasesFileName, []byte(data), 0644)
|
||||
}
|
||||
|
||||
func (lan *LAN) SetAliasFor(mac, alias string) bool {
|
||||
lan.Lock()
|
||||
defer lan.Unlock()
|
||||
|
||||
if t, found := lan.Hosts[mac]; found == true {
|
||||
if alias != "" {
|
||||
lan.Aliases[mac] = alias
|
||||
} else {
|
||||
delete(lan.Aliases, mac)
|
||||
}
|
||||
|
||||
t.Alias = alias
|
||||
lan.saveAliases()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (lan *LAN) WasMissed(mac string) bool {
|
||||
if mac == lan.Interface.HwAddress || mac == lan.Gateway.HwAddress {
|
||||
if mac == lan.iface.HwAddress || mac == lan.gateway.HwAddress {
|
||||
return false
|
||||
}
|
||||
|
||||
lan.Lock()
|
||||
defer lan.Unlock()
|
||||
|
||||
if ttl, found := lan.TTL[mac]; found == true {
|
||||
return ttl < LANDefaultTTL
|
||||
if ttl, found := lan.ttl[mac]; found == true {
|
||||
return ttl < LANDefaultttl
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -129,33 +96,36 @@ func (lan *LAN) Remove(ip, mac string) {
|
|||
defer lan.Unlock()
|
||||
|
||||
if e, found := lan.Hosts[mac]; found {
|
||||
lan.TTL[mac]--
|
||||
if lan.TTL[mac] == 0 {
|
||||
lan.ttl[mac]--
|
||||
if lan.ttl[mac] == 0 {
|
||||
delete(lan.Hosts, mac)
|
||||
delete(lan.TTL, mac)
|
||||
|
||||
delete(lan.ttl, mac)
|
||||
lan.lostCb(e)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (lan *LAN) shouldIgnore(ip string) bool {
|
||||
func (lan *LAN) shouldIgnore(ip, mac string) bool {
|
||||
// skip our own address
|
||||
if ip == lan.Interface.IpAddress {
|
||||
if ip == lan.iface.IpAddress {
|
||||
return true
|
||||
}
|
||||
// skip the gateway
|
||||
if ip == lan.Gateway.IpAddress {
|
||||
if ip == lan.gateway.IpAddress {
|
||||
return true
|
||||
}
|
||||
// skip broadcast addresses
|
||||
if strings.HasSuffix(ip, ".255") {
|
||||
if strings.HasSuffix(ip, BroadcastSuffix) {
|
||||
return true
|
||||
}
|
||||
// skip broadcast macs
|
||||
if strings.ToLower(mac) == BroadcastMac {
|
||||
return true
|
||||
}
|
||||
// skip everything which is not in our subnet (multicast noise)
|
||||
addr := net.ParseIP(ip)
|
||||
return lan.Interface.Net.Contains(addr) == false
|
||||
return lan.iface.Net.Contains(addr) == false
|
||||
}
|
||||
|
||||
func (lan *LAN) Has(ip string) bool {
|
||||
|
@ -171,7 +141,16 @@ func (lan *LAN) Has(ip string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (lan *LAN) Get(ip string) *Endpoint {
|
||||
func (lan *LAN) EachHost(cb func(mac string, e *Endpoint)) {
|
||||
lan.Lock()
|
||||
defer lan.Unlock()
|
||||
|
||||
for m, h := range lan.Hosts {
|
||||
cb(m, h)
|
||||
}
|
||||
}
|
||||
|
||||
func (lan *LAN) GetByIp(ip string) *Endpoint {
|
||||
lan.Lock()
|
||||
defer lan.Unlock()
|
||||
|
||||
|
@ -188,25 +167,21 @@ func (lan *LAN) AddIfNew(ip, mac string) *Endpoint {
|
|||
lan.Lock()
|
||||
defer lan.Unlock()
|
||||
|
||||
if lan.shouldIgnore(ip) {
|
||||
return nil
|
||||
}
|
||||
|
||||
mac = NormalizeMac(mac)
|
||||
if t, found := lan.Hosts[mac]; found {
|
||||
if lan.TTL[mac] < LANDefaultTTL {
|
||||
lan.TTL[mac]++
|
||||
|
||||
if lan.shouldIgnore(ip, mac) {
|
||||
return nil
|
||||
} else if t, found := lan.Hosts[mac]; found {
|
||||
if lan.ttl[mac] < LANDefaultttl {
|
||||
lan.ttl[mac]++
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
e := NewEndpoint(ip, mac)
|
||||
if alias, found := lan.Aliases[mac]; found {
|
||||
e.Alias = alias
|
||||
}
|
||||
e := NewEndpointWithAlias(ip, mac, lan.aliases.Get(mac))
|
||||
|
||||
lan.Hosts[mac] = e
|
||||
lan.TTL[mac] = LANDefaultTTL
|
||||
lan.ttl[mac] = LANDefaultttl
|
||||
|
||||
lan.newCb(e)
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ func NewEndpoint(ip, mac string) *Endpoint {
|
|||
|
||||
// start resolver goroutine
|
||||
go func() {
|
||||
if names, err := net.LookupAddr(e.IpAddress); err == nil {
|
||||
if names, err := net.LookupAddr(e.IpAddress); err == nil && len(names) > 0 {
|
||||
e.Hostname = names[0]
|
||||
if e.ResolvedCallback != nil {
|
||||
e.ResolvedCallback(e)
|
||||
|
@ -80,6 +80,12 @@ func NewEndpoint(ip, mac string) *Endpoint {
|
|||
return e
|
||||
}
|
||||
|
||||
func NewEndpointWithAlias(ip, mac, alias string) *Endpoint {
|
||||
e := NewEndpoint(ip, mac)
|
||||
e.Alias = alias
|
||||
return e
|
||||
}
|
||||
|
||||
func (t *Endpoint) Name() string {
|
||||
return t.Hostname
|
||||
}
|
||||
|
|
|
@ -12,12 +12,14 @@ import (
|
|||
|
||||
const (
|
||||
MonitorModeAddress = "0.0.0.0"
|
||||
BroadcastSuffix = ".255"
|
||||
BroadcastMac = "ff:ff:ff:ff:ff:ff"
|
||||
IPv4MulticastStart = "01:00:5e:00:00:00"
|
||||
IPv4MulticastEnd = "01:00:5e:7f:ff:ff"
|
||||
)
|
||||
|
||||
var (
|
||||
BroadcastMac = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||||
BroadcastHw = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||||
IPv4Validator = regexp.MustCompile("^[0-9\\.]+/?\\d*$")
|
||||
)
|
||||
|
||||
|
@ -60,7 +62,9 @@ func FindInterface(name string) (*Endpoint, error) {
|
|||
* if passed explicitly.
|
||||
*/
|
||||
doCheck := false
|
||||
if name == "" && ifName != "lo" && ifName != "lo0" && nAddrs > 0 {
|
||||
if name == mac {
|
||||
doCheck = true
|
||||
} else if name == "" && ifName != "lo" && ifName != "lo0" && nAddrs > 0 {
|
||||
doCheck = true
|
||||
} else if ifName == name {
|
||||
doCheck = true
|
||||
|
|
|
@ -12,19 +12,20 @@ var Channels5Ghz = [...]int{36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60,
|
|||
|
||||
type WiFi struct {
|
||||
sync.Mutex
|
||||
Interface *Endpoint
|
||||
Stations map[string]*Station
|
||||
|
||||
Stations map[string]*Station
|
||||
|
||||
iface *Endpoint
|
||||
newCb StationNewCallback
|
||||
lostCb StationLostCallback
|
||||
}
|
||||
|
||||
func NewWiFi(iface *Endpoint, newcb StationNewCallback, lostcb StationLostCallback) *WiFi {
|
||||
return &WiFi{
|
||||
Interface: iface,
|
||||
Stations: make(map[string]*Station),
|
||||
newCb: newcb,
|
||||
lostCb: lostcb,
|
||||
Stations: make(map[string]*Station),
|
||||
iface: iface,
|
||||
newCb: newcb,
|
||||
lostCb: lostcb,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ func DHCP6EncodeList(elements []string) (encoded []byte) {
|
|||
encoded = make([]byte, 0)
|
||||
|
||||
for _, elem := range elements {
|
||||
// this would be worth fuzzing btw
|
||||
encoded = append(encoded, byte(len(elem)&0xff))
|
||||
encoded = append(encoded, []byte(elem)...)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ type Environment struct {
|
|||
sync.Mutex
|
||||
|
||||
Padding int `json:"-"`
|
||||
Storage map[string]string `json:"storage"`
|
||||
Data map[string]string `json:"data"`
|
||||
|
||||
cbs map[string]SetCallback
|
||||
sess *Session
|
||||
|
@ -24,7 +24,7 @@ type Environment struct {
|
|||
func NewEnvironment(s *Session) *Environment {
|
||||
env := &Environment{
|
||||
Padding: 0,
|
||||
Storage: make(map[string]string),
|
||||
Data: make(map[string]string),
|
||||
sess: s,
|
||||
cbs: make(map[string]SetCallback),
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ func (env *Environment) Has(name string) bool {
|
|||
env.Lock()
|
||||
defer env.Unlock()
|
||||
|
||||
_, found := env.Storage[name]
|
||||
_, found := env.Data[name]
|
||||
|
||||
return found
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ func (env *Environment) Set(name, value string) string {
|
|||
env.Lock()
|
||||
defer env.Unlock()
|
||||
|
||||
old, _ := env.Storage[name]
|
||||
env.Storage[name] = value
|
||||
old, _ := env.Data[name]
|
||||
env.Data[name] = value
|
||||
|
||||
if cb, hasCallback := env.cbs[name]; hasCallback == true {
|
||||
cb(value)
|
||||
|
@ -78,7 +78,7 @@ func (env *Environment) Get(name string) (bool, string) {
|
|||
env.Lock()
|
||||
defer env.Unlock()
|
||||
|
||||
if value, found := env.Storage[name]; found == true {
|
||||
if value, found := env.Data[name]; found == true {
|
||||
return true, value
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ func (env *Environment) Sorted() []string {
|
|||
defer env.Unlock()
|
||||
|
||||
var keys []string
|
||||
for k := range env.Storage {
|
||||
for k := range env.Data {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
|
|
@ -100,12 +100,6 @@ func (p *EventPool) Clear() {
|
|||
p.events = make([]Event, 0)
|
||||
}
|
||||
|
||||
func (p *EventPool) Events() []Event {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
return p.events
|
||||
}
|
||||
|
||||
func (p *EventPool) Sorted() []Event {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
|
|
@ -56,7 +56,7 @@ var PromptCallbacks = map[string]func(s *Session) string{
|
|||
},
|
||||
}
|
||||
|
||||
var envRe = regexp.MustCompile("{env\\.(.+)}")
|
||||
var envRe = regexp.MustCompile("{env\\.([^}]+)}")
|
||||
|
||||
type Prompt struct {
|
||||
}
|
||||
|
@ -79,11 +79,11 @@ func (p Prompt) Render(s *Session) string {
|
|||
prompt = strings.Replace(prompt, tok, cb(s), -1)
|
||||
}
|
||||
|
||||
m := envRe.FindStringSubmatch(prompt)
|
||||
if len(m) == 2 {
|
||||
name := m[1]
|
||||
m := envRe.FindAllString(prompt, -1)
|
||||
for _, match := range m {
|
||||
name := strings.Trim(strings.Replace(match, "env.", "", -1), "{}")
|
||||
_, value := s.Env.Get(name)
|
||||
prompt = strings.Replace(prompt, m[0], value, -1)
|
||||
prompt = strings.Replace(prompt, match, value, -1)
|
||||
}
|
||||
|
||||
// make sure an user error does not screw all terminal
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/evilsocket/bettercap-ng/core"
|
||||
"github.com/evilsocket/bettercap-ng/network"
|
||||
|
||||
"github.com/evilsocket/readline"
|
||||
)
|
||||
|
@ -132,7 +133,7 @@ func (s *Session) getHandler(args []string, sess *Session) error {
|
|||
prev_ns = ns
|
||||
}
|
||||
|
||||
fmt.Printf(" %"+strconv.Itoa(s.Env.Padding)+"s: '%s'\n", k, s.Env.Storage[k])
|
||||
fmt.Printf(" %"+strconv.Itoa(s.Env.Padding)+"s: '%s'\n", k, s.Env.Data[k])
|
||||
}
|
||||
fmt.Println()
|
||||
} else if found, value := s.Env.Get(key); found == true {
|
||||
|
@ -241,7 +242,7 @@ func (s *Session) registerCoreHandlers() {
|
|||
readline.PcItem("get", readline.PcItemDynamic(func(prefix string) []string {
|
||||
prefix = core.Trim(prefix[3:])
|
||||
varNames := []string{""}
|
||||
for key := range s.Env.Storage {
|
||||
for key := range s.Env.Data {
|
||||
if prefix == "" || strings.HasPrefix(key, prefix) == true {
|
||||
varNames = append(varNames, key)
|
||||
}
|
||||
|
@ -256,7 +257,7 @@ func (s *Session) registerCoreHandlers() {
|
|||
readline.PcItem("set", readline.PcItemDynamic(func(prefix string) []string {
|
||||
prefix = core.Trim(prefix[3:])
|
||||
varNames := []string{""}
|
||||
for key := range s.Env.Storage {
|
||||
for key := range s.Env.Data {
|
||||
if prefix == "" || strings.HasPrefix(key, prefix) == true {
|
||||
varNames = append(varNames, key)
|
||||
}
|
||||
|
@ -298,11 +299,11 @@ func (s *Session) registerCoreHandlers() {
|
|||
readline.PcItem("alias", readline.PcItemDynamic(func(prefix string) []string {
|
||||
prefix = core.Trim(prefix[5:])
|
||||
macs := []string{""}
|
||||
for mac := range s.Lan.Hosts {
|
||||
s.Lan.EachHost(func(mac string, e *network.Endpoint) {
|
||||
if prefix == "" || strings.HasPrefix(mac, prefix) == true {
|
||||
macs = append(macs, mac)
|
||||
}
|
||||
}
|
||||
})
|
||||
return macs
|
||||
})))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue