Commit dcaf42df authored by Sophie Brun's avatar Sophie Brun

New upstream version 2.13.1

parent eeeb3db8
......@@ -2,7 +2,7 @@ package core
const (
Name = "bettercap"
Version = "2.13"
Version = "2.13.1"
Author = "Simone 'evilsocket' Margaritelli"
Website = "https://bettercap.org/"
)
......@@ -4,6 +4,7 @@ import (
"fmt"
"time"
"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/session"
"github.com/google/gopacket"
......@@ -170,6 +171,7 @@ func (s *Sniffer) Start() error {
s.pktSourceChan = src.Packets()
for packet := range s.pktSourceChan {
if !s.Running() {
log.Debug("end pkt loop (pkt=%v filter='%s')", packet, s.Ctx.Filter)
break
}
......@@ -209,9 +211,14 @@ func (s *Sniffer) Start() error {
func (s *Sniffer) Stop() error {
return s.SetRunning(false, func() {
log.Debug("stopping sniffer")
if s.pktSourceChan != nil {
log.Debug("sending nil")
s.pktSourceChan <- nil
log.Debug("nil sent")
}
log.Debug("closing ctx")
s.Ctx.Close()
log.Debug("ctx closed")
})
}
......@@ -3,6 +3,7 @@ package modules
import (
"os"
"regexp"
"time"
"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/session"
......@@ -36,7 +37,12 @@ func (s *Sniffer) GetContext() (error, *SnifferContext) {
}
if ctx.Source == "" {
if ctx.Handle, err = pcap.OpenLive(s.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil {
/*
* We don't want to pcap.BlockForever otherwise pcap_close(handle)
* could hang waiting for a timeout to expire ...
*/
readTimeout := 500 * time.Millisecond
if ctx.Handle, err = pcap.OpenLive(s.Session.Interface.Name(), 65536, true, readTimeout); err != nil {
return err, ctx
}
} else {
......@@ -117,12 +123,16 @@ func (c *SnifferContext) Log(sess *session.Session) {
func (c *SnifferContext) Close() {
if c.Handle != nil {
log.Debug("closing handle")
c.Handle.Close()
log.Debug("handle closed")
c.Handle = nil
}
if c.OutputFile != nil {
log.Debug("closing output")
c.OutputFile.Close()
log.Debug("output closed")
c.OutputFile = nil
}
}
package modules
import (
"strings"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"strings"
"github.com/evilsocket/islazy/tui"
)
......@@ -20,17 +19,31 @@ func dnsParser(ip *layers.IPv4, pkt gopacket.Packet, udp *layers.UDP) bool {
}
m := make(map[string][]string)
for _, a := range dns.Answers {
if a.IP == nil {
continue
}
answers := [][]layers.DNSResourceRecord{
dns.Answers,
dns.Authorities,
dns.Additionals,
}
hostname := string(a.Name)
if _, found := m[hostname]; !found {
m[hostname] = make([]string, 0)
for _, list := range answers {
for _, a := range list {
if a.IP == nil {
continue
}
hostname := string(a.Name)
if _, found := m[hostname]; !found {
m[hostname] = make([]string, 0)
}
m[hostname] = append(m[hostname], vIP(a.IP))
}
}
m[hostname] = append(m[hostname], vIP(a.IP))
if len(m) == 0 && dns.ResponseCode != layers.DNSResponseCodeNoErr {
for _, a := range dns.Questions {
m[string(a.Name)] = []string{tui.Red(dns.ResponseCode.String())}
}
}
for hostname, ips := range m {
......
......@@ -5,7 +5,7 @@ import (
"github.com/google/gopacket/layers"
)
func dot11Parser(radiotap *layers.RadioTap, dot11 *layers.Dot11, pkt gopacket.Packet, verbose bool) {
func onDOT11(radiotap *layers.RadioTap, dot11 *layers.Dot11, pkt gopacket.Packet, verbose bool) {
NewSnifferEvent(
pkt.Metadata().Timestamp,
"802.11",
......
package modules
import (
"regexp"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/evilsocket/islazy/str"
"github.com/evilsocket/islazy/tui"
)
var (
ftpRe = regexp.MustCompile(`^(USER|PASS) (.+)[\n\r]+$`)
)
func ftpParser(ip *layers.IPv4, pkt gopacket.Packet, tcp *layers.TCP) bool {
data := string(tcp.Payload)
if matches := ftpRe.FindAllStringSubmatch(data, -1); matches != nil {
what := str.Trim(matches[0][1])
cred := str.Trim(matches[0][2])
NewSnifferEvent(
pkt.Metadata().Timestamp,
"ftp",
ip.SrcIP.String(),
ip.DstIP.String(),
nil,
"%s %s > %s:%s - %s %s",
tui.Wrap(tui.BACKYELLOW+tui.FOREWHITE, "ftp"),
vIP(ip.SrcIP),
vIP(ip.DstIP),
vPort(tcp.DstPort),
tui.Bold(what),
tui.Yellow(cred),
).Push()
return true
}
return false
}
......@@ -12,67 +12,7 @@ import (
"github.com/evilsocket/islazy/tui"
)
func tcpParser(ip *layers.IPv4, pkt gopacket.Packet, verbose bool) {
tcp := pkt.Layer(layers.LayerTypeTCP).(*layers.TCP)
if sniParser(ip, pkt, tcp) {
return
} else if ntlmParser(ip, pkt, tcp) {
return
} else if httpParser(ip, pkt, tcp) {
return
} else if verbose {
NewSnifferEvent(
pkt.Metadata().Timestamp,
"tcp",
fmt.Sprintf("%s:%s", ip.SrcIP, vPort(tcp.SrcPort)),
fmt.Sprintf("%s:%s", ip.DstIP, vPort(tcp.DstPort)),
SniffData{
"Size": len(ip.Payload),
},
"%s %s:%s > %s:%s %s",
tui.Wrap(tui.BACKLIGHTBLUE+tui.FOREBLACK, "tcp"),
vIP(ip.SrcIP),
vPort(tcp.SrcPort),
vIP(ip.DstIP),
vPort(tcp.DstPort),
tui.Dim(fmt.Sprintf("%d bytes", len(ip.Payload))),
).Push()
}
}
func udpParser(ip *layers.IPv4, pkt gopacket.Packet, verbose bool) {
udp := pkt.Layer(layers.LayerTypeUDP).(*layers.UDP)
if dnsParser(ip, pkt, udp) {
return
} else if mdnsParser(ip, pkt, udp) {
return
} else if krb5Parser(ip, pkt, udp) {
return
} else if upnpParser(ip, pkt, udp) {
return
} else if verbose {
NewSnifferEvent(
pkt.Metadata().Timestamp,
"udp",
fmt.Sprintf("%s:%s", ip.SrcIP, vPort(udp.SrcPort)),
fmt.Sprintf("%s:%s", ip.DstIP, vPort(udp.DstPort)),
SniffData{
"Size": len(ip.Payload),
},
"%s %s:%s > %s:%s %s",
tui.Wrap(tui.BACKDARKGRAY+tui.FOREWHITE, "udp"),
vIP(ip.SrcIP),
vPort(udp.SrcPort),
vIP(ip.DstIP),
vPort(udp.DstPort),
tui.Dim(fmt.Sprintf("%d bytes", len(ip.Payload))),
).Push()
}
}
func unkParser(ip *layers.IPv4, pkt gopacket.Packet, verbose bool) {
func onUNK(ip *layers.IPv4, pkt gopacket.Packet, verbose bool) {
if verbose {
NewSnifferEvent(
pkt.Metadata().Timestamp,
......@@ -111,16 +51,16 @@ func mainParser(pkt gopacket.Packet, verbose bool) bool {
}
if tlayer.LayerType() == layers.LayerTypeTCP {
tcpParser(ip, pkt, verbose)
onTCP(ip, pkt, verbose)
} else if tlayer.LayerType() == layers.LayerTypeUDP {
udpParser(ip, pkt, verbose)
onUDP(ip, pkt, verbose)
} else {
unkParser(ip, pkt, verbose)
onUNK(ip, pkt, verbose)
}
return true
} else if ok, radiotap, dot11 := packets.Dot11Parse(pkt); ok {
// are we sniffing in monitor mode?
dot11Parser(radiotap, dot11, pkt, verbose)
onDOT11(radiotap, dot11, pkt, verbose)
return true
}
return false
......
package modules
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/evilsocket/islazy/tui"
)
var tcpParsers = []func(*layers.IPv4, gopacket.Packet, *layers.TCP) bool{
sniParser,
ntlmParser,
httpParser,
ftpParser,
teamViewerParser,
}
func onTCP(ip *layers.IPv4, pkt gopacket.Packet, verbose bool) {
tcp := pkt.Layer(layers.LayerTypeTCP).(*layers.TCP)
for _, parser := range tcpParsers {
if parser(ip, pkt, tcp) {
return
}
}
if verbose {
NewSnifferEvent(
pkt.Metadata().Timestamp,
"tcp",
fmt.Sprintf("%s:%s", ip.SrcIP, vPort(tcp.SrcPort)),
fmt.Sprintf("%s:%s", ip.DstIP, vPort(tcp.DstPort)),
SniffData{
"Size": len(ip.Payload),
},
"%s %s:%s > %s:%s %s",
tui.Wrap(tui.BACKLIGHTBLUE+tui.FOREBLACK, "tcp"),
vIP(ip.SrcIP),
vPort(tcp.SrcPort),
vIP(ip.DstIP),
vPort(tcp.DstPort),
tui.Dim(fmt.Sprintf("%d bytes", len(ip.Payload))),
).Push()
}
}
package modules
import (
"github.com/bettercap/bettercap/packets"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/evilsocket/islazy/tui"
)
func teamViewerParser(ip *layers.IPv4, pkt gopacket.Packet, tcp *layers.TCP) bool {
if tcp.SrcPort == packets.TeamViewerPort || tcp.DstPort == packets.TeamViewerPort {
if tv := packets.ParseTeamViewer(tcp.Payload); tv != nil {
NewSnifferEvent(
pkt.Metadata().Timestamp,
"teamviewer",
ip.SrcIP.String(),
ip.DstIP.String(),
nil,
"%s %s %s > %s",
tui.Wrap(tui.BACKYELLOW+tui.FOREWHITE, "teamviewer"),
vIP(ip.SrcIP),
tui.Yellow(tv.Command),
vIP(ip.DstIP),
).Push()
return true
}
}
return false
}
package modules
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/evilsocket/islazy/tui"
)
var udpParsers = []func(*layers.IPv4, gopacket.Packet, *layers.UDP) bool{
dnsParser,
mdnsParser,
krb5Parser,
upnpParser,
}
func onUDP(ip *layers.IPv4, pkt gopacket.Packet, verbose bool) {
udp := pkt.Layer(layers.LayerTypeUDP).(*layers.UDP)
for _, parser := range udpParsers {
if parser(ip, pkt, udp) {
return
}
}
if verbose {
NewSnifferEvent(
pkt.Metadata().Timestamp,
"udp",
fmt.Sprintf("%s:%s", ip.SrcIP, vPort(udp.SrcPort)),
fmt.Sprintf("%s:%s", ip.DstIP, vPort(udp.DstPort)),
SniffData{
"Size": len(ip.Payload),
},
"%s %s:%s > %s:%s %s",
tui.Wrap(tui.BACKDARKGRAY+tui.FOREWHITE, "udp"),
vIP(ip.SrcIP),
vPort(udp.SrcPort),
vIP(ip.DstIP),
vPort(udp.DstPort),
tui.Dim(fmt.Sprintf("%d bytes", len(ip.Payload))),
).Push()
}
}
......@@ -236,7 +236,13 @@ func (w *WiFiModule) Configure() error {
return fmt.Errorf("Error while setting interface %s in monitor mode: %s", tui.Bold(w.Session.Interface.Name()), err)
} else if err = ihandle.SetSnapLen(65536); err != nil {
return err
} else if err = ihandle.SetTimeout(pcap.BlockForever); err != nil {
}
/*
* 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 err
} else if w.handle, err = ihandle.Activate(); err != nil {
return err
......
......@@ -215,15 +215,11 @@ func (w *WiFiModule) colDecorate(colNames []string, name string, dir string) {
}
}
func (w *WiFiModule) colNames(nrows int, withWPS bool) []string {
func (w *WiFiModule) colNames(nrows int) []string {
columns := []string(nil)
if !w.isApSelected() {
if withWPS {
columns = []string{"RSSI", "BSSID", "SSID", "Encryption", "WPS", "Ch", "Clients", "Sent", "Recvd", "Last Seen"}
} else {
columns = []string{"RSSI", "BSSID", "SSID", "Encryption", "Ch", "Clients", "Sent", "Recvd", "Last Seen"}
}
columns = []string{"RSSI", "BSSID", "SSID", "Encryption", "WPS", "Ch", "Clients", "Sent", "Recvd", "Last Seen"}
} else if nrows > 0 {
columns = []string{"RSSI", "MAC", "Ch", "Sent", "Received", "Last Seen"}
fmt.Printf("\n%s clients:\n", w.ap.HwAddress)
......@@ -263,19 +259,15 @@ func (w *WiFiModule) Show() (err error) {
return
}
hasWPS := false
rows := make([][]string, 0)
for _, s := range stations {
if row, include := w.getRow(s); include {
if len(s.WPS) > 0 {
hasWPS = true
}
rows = append(rows, row)
}
}
nrows := len(rows)
if nrows > 0 {
tui.Table(os.Stdout, w.colNames(nrows, hasWPS), rows)
tui.Table(os.Stdout, w.colNames(nrows), rows)
}
w.Session.Queue.Stats.RLock()
......
package packets
import (
"encoding/binary"
"fmt"
)
const TeamViewerPort = 5938
var teamViewerCommands = map[uint8]string{
10: "CMD_IDENTIFY",
11: "CMD_REQUESTCONNECT",
13: "CMD_DISCONNECT",
14: "CMD_VNCDISCONNECT",
15: "CMD_TVCONNECTIONFAILED",
16: "CMD_PING",
17: "CMD_PINGOK",
18: "CMD_MASTERCOMMAND",
19: "CMD_MASTERRESPONSE",
20: "CMD_CHANGECONNECTION",
21: "CMD_NOPARTNERCONNECT",
22: "CMD_CONNECTTOWAITINGTHREAD",
23: "CMD_SESSIONMODE",
24: "CMD_REQUESTROUTINGSESSION",
25: "CMD_TIMEOUT",
26: "CMD_JAVACONNECT",
27: "CMD_KEEPALIVEBEEP",
28: "CMD_REQUESTKEEPALIVE",
29: "CMD_MASTERCOMMAND_ENCRYPTED",
30: "CMD_MASTERRESPONSE_ENCRYPTED",
31: "CMD_REQUESTRECONNECT",
32: "CMD_RECONNECTTOWAITINGTHREAD",
33: "CMD_STARTLOGGING",
34: "CMD_SERVERAVAILABLE",
35: "CMD_KEEPALIVEREQUEST",
36: "CMD_OK",
37: "CMD_FAILED",
38: "CMD_PING_PERFORMANCE",
39: "CMD_PING_PERFORMANCE_RESPONSE",
40: "CMD_REQUESTKEEPALIVE2",
41: "CMD_DISCONNECT_SWITCHEDTOUDP",
42: "CMD_SENDMODE_UDP",
43: "CMD_KEEPALIVEREQUEST_ANSWER",
44: "CMD_ROUTE_CMD_TO_CLIENT",
45: "CMD_NEW_MASTERLOGIN",
46: "CMD_BUDDY",
47: "CMD_ACCEPTROUTINGSESSION",
48: "CMD_NEW_MASTERLOGIN_ANSWER",
49: "CMD_BUDDY_ENCRYPTED",
50: "CMD_REQUEST_ROUTE_BUDDY",
51: "CMD_CONTACT_OTHER_MASTER",
52: "CMD_REQUEST_ROUTE_ENCRYPTED",
53: "CMD_ENDSESSION",
54: "CMD_SESSIONID",
55: "CMD_RECONNECT_TO_SESSION",
56: "CMD_RECONNECT_TO_SESSION_ANSWER",
57: "CMD_MEETING_CONTROL",
58: "CMD_CARRIER_SWITCH",
59: "CMD_MEETING_AUTHENTICATION",
60: "CMD_ROUTERCMD",
61: "CMD_PARTNERRECONNECT",
62: "CMD_CONGRESTION_CONTROL",
63: "CMD_ACK",
70: "CMD_UDPREQUESTCONNECT",
71: "CMD_UDPPING",
72: "CMD_UDPREQUESTCONNECT_VPN",
90: "CMD_DATA",
91: "CMD_DATA2",
92: "CMD_DATA_ENCRYPTED",
93: "CMD_REQUESTENCRYPTION",
94: "CMD_CONFIRMENCRYPTION",
95: "CMD_ENCRYPTIONREQUESTFAILED",
96: "CMD_REQUESTNOENCRYPTION",
97: "CMD_UDPFLOWCONTROL",
98: "CMD_DATA3",
99: "CMD_DATA3_ENCRYPTED",
100: "CMD_DATA3_RESENDPACKETS",
101: "CMD_DATA3_ACKPACKETS",
102: "CMD_AUTH_CHALLENGE",
103: "CMD_AUTH_RESPONSE",
104: "CMD_AUTH_RESULT",
105: "CMD_RIP_MESSAGES",
106: "CMD_DATA4",
107: "CMD_DATASTREAM",
108: "CMD_UDPHEARTBEAT",
109: "CMD_DATA_DIRECTED",
110: "CMD_UDP_RESENDPACKETS",
111: "CMD_UDP_ACKPACKETS",
112: "CMD_UDP_PROTECTEDCOMMAND",
113: "CMD_FLUSHSENDBUFFER",
}
type TeamViewerPacket struct {
Magic uint16
Version string
CommandCode uint8
Command string
}
func ParseTeamViewer(data []byte) *TeamViewerPacket {
if len(data) < 3 {
return nil
}
magic := binary.BigEndian.Uint16(data[0:2])
cmdCode := uint8(data[3])
version := "1.x"
cmd := "CMD_?"
if magic == 0x1724 {
version = "1.x"
} else if magic == 0x1130 {
version = "2.x"
} else {
version = fmt.Sprintf("?.? (magic=0x%x)", magic)
}
if val, found := teamViewerCommands[cmdCode]; !found {
return nil
} else {
cmd = val
}
return &TeamViewerPacket{
Magic: magic,
Version: version,
CommandCode: cmdCode,
Command: cmd,
}
}
name: bettercap
version: '2.13'
version: '2.13.1'
summary: 802.11, BLE and Ethernet networks reconnaissance and MITM attacks tool.
description: |
The Swiss Army knife for 802.11, BLE and Ethernet networks reconnaissance and MITM attacks.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment