This commit is contained in:
Krzysiekk310895 2022-08-10 01:32:42 +00:00 committed by GitHub
commit 15ce350767
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 785 additions and 512 deletions

View file

@ -83,6 +83,7 @@ matrix:
- name: OSX - amd64 - name: OSX - amd64
if: tag IS present if: tag IS present
os: osx os: osx
osx_image: xcode12.5
arch: amd64 arch: amd64
addons: addons:
homebrew: homebrew:
@ -142,6 +143,7 @@ matrix:
- name: OSX - tests - name: OSX - tests
if: tag IS blank if: tag IS blank
os: osx os: osx
osx_image: xcode12.5
arch: amd64 arch: amd64
allow_failures: allow_failures:
- go: master - go: master

View file

@ -3,8 +3,8 @@ FROM golang:alpine AS build-env
ENV SRC_DIR $GOPATH/src/github.com/bettercap/bettercap ENV SRC_DIR $GOPATH/src/github.com/bettercap/bettercap
RUN apk add --update ca-certificates RUN apk add --no-cache ca-certificates
RUN apk add --no-cache --update bash iptables wireless-tools build-base libpcap-dev libusb-dev linux-headers libnetfilter_queue-dev git RUN apk add --no-cache bash iptables wireless-tools build-base libpcap-dev libusb-dev linux-headers libnetfilter_queue-dev git
WORKDIR $SRC_DIR WORKDIR $SRC_DIR
ADD . $SRC_DIR ADD . $SRC_DIR
@ -16,8 +16,8 @@ RUN git clone https://github.com/bettercap/caplets /usr/local/share/bettercap/ca
# final stage # final stage
FROM alpine FROM alpine
RUN apk add --update ca-certificates RUN apk add --no-cache ca-certificates
RUN apk add --no-cache --update bash iproute2 libpcap libusb-dev libnetfilter_queue wireless-tools RUN apk add --no-cache bash iproute2 libpcap libusb-dev libnetfilter_queue wireless-tools
COPY --from=build-env /go/src/github.com/bettercap/bettercap/bettercap /app/ COPY --from=build-env /go/src/github.com/bettercap/bettercap/bettercap /app/
COPY --from=build-env /usr/local/share/bettercap/caplets /app/ COPY --from=build-env /usr/local/share/bettercap/caplets /app/
WORKDIR /app WORKDIR /app

View file

@ -2,15 +2,14 @@ TARGET ?= bettercap
PACKAGES ?= core firewall log modules network packets session tls PACKAGES ?= core firewall log modules network packets session tls
PREFIX ?= /usr/local PREFIX ?= /usr/local
GO ?= go GO ?= go
GOFLAGS ?=
all: build all: build
build: resources build: resources
$(GO) $(GOFLAGS) build -o $(TARGET) . $(GOFLAGS) $(GO) build -o $(TARGET) .
build_with_race_detector: resources build_with_race_detector: resources
$(GO) $(GOFLAGS) build -race -o $(TARGET) . $(GOFLAGS) $(GO) build -race -o $(TARGET) .
resources: network/manuf.go resources: network/manuf.go
@ -18,20 +17,20 @@ network/manuf.go:
@python3 ./network/make_manuf.py @python3 ./network/make_manuf.py
install: install:
@mkdir -p $(PREFIX)/share/bettercap/caplets @mkdir -p $(DESTDIR)$(PREFIX)/share/bettercap/caplets
@cp bettercap $(PREFIX)/bin/ @cp bettercap $(DESTDIR)$(PREFIX)/bin/
docker: docker:
@docker build -t bettercap:latest . @docker build -t bettercap:latest .
test: test:
$(GO) $(GOFLAGS) test -covermode=atomic -coverprofile=cover.out ./... $(GOFLAGS) $(GO) test -covermode=atomic -coverprofile=cover.out ./...
html_coverage: test html_coverage: test
$(GO) $(GOFLAGS) tool cover -html=cover.out -o cover.out.html $(GOFLAGS) $(GO) tool cover -html=cover.out -o cover.out.html
benchmark: server_deps benchmark: server_deps
$(GO) $(GOFLAGS) test -v -run=doNotRunTests -bench=. -benchmem ./... $(GOFLAGS) $(GO) test -v -run=doNotRunTests -bench=. -benchmem ./...
fmt: fmt:
$(GO) fmt -s -w $(PACKAGES) $(GO) fmt -s -w $(PACKAGES)

View file

@ -2,7 +2,7 @@ package core
const ( const (
Name = "bettercap" Name = "bettercap"
Version = "2.31.0" Version = "2.32.0"
Author = "Simone 'evilsocket' Margaritelli" Author = "Simone 'evilsocket' Margaritelli"
Website = "https://bettercap.org/" Website = "https://bettercap.org/"
) )

View file

@ -41,7 +41,7 @@ func Exec(executable string, args []string) (string, error) {
raw, err := exec.Command(path, args...).CombinedOutput() raw, err := exec.Command(path, args...).CombinedOutput()
if err != nil { if err != nil {
return "", err return str.Trim(string(raw)), err
} else { } else {
return str.Trim(string(raw)), nil return str.Trim(string(raw)), nil
} }

View file

@ -1,13 +1,10 @@
package core package core
import ( import (
"bytes"
"io"
"os" "os"
"testing" "testing"
"github.com/evilsocket/islazy/fs" "github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/str"
) )
func hasInt(a []int, v int) bool { func hasInt(a []int, v int) bool {
@ -81,85 +78,6 @@ func TestCoreUniqueIntsSorted(t *testing.T) {
} }
} }
func sameStrings(a []string, b []string) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
func TestCoreExec(t *testing.T) {
var units = []struct {
exec string
args []string
out string
err string
stdout string
}{
{"foo", []string{}, "", `exec: "foo": executable file not found in $PATH`, ""},
{"ps", []string{"-someinvalidflag"}, "", "exit status 1", ""},
{"true", []string{}, "", "", ""},
{"head", []string{"/path/to/file/that/does/not/exist"}, "", "exit status 1", ""},
}
for _, u := range units {
var buf bytes.Buffer
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
gotOut, gotErr := Exec(u.exec, u.args)
w.Close()
io.Copy(&buf, r)
os.Stdout = oldStdout
gotStdout := str.Trim(buf.String())
if gotOut != u.out {
t.Fatalf("expected output '%s', got '%s'", u.out, gotOut)
} else if u.err == "" && gotErr != nil {
t.Fatalf("expected no error, got '%s'", gotErr)
} else if u.err != "" && gotErr == nil {
t.Fatalf("expected error '%s', got none", u.err)
} else if u.err != "" && gotErr != nil && gotErr.Error() != u.err {
t.Fatalf("expected error '%s', got '%s'", u.err, gotErr)
} else if gotStdout != "" {
t.Fatalf("expected empty stdout, got '%s'", gotStdout)
}
}
for _, u := range units {
var buf bytes.Buffer
oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
gotOut, gotErr := Exec(u.exec, u.args)
w.Close()
io.Copy(&buf, r)
os.Stdout = oldStdout
gotStdout := str.Trim(buf.String())
if gotOut != u.out {
t.Fatalf("expected output '%s', got '%s'", u.out, gotOut)
} else if u.err == "" && gotErr != nil {
t.Fatalf("expected no error, got '%s'", gotErr)
} else if u.err != "" && gotErr == nil {
t.Fatalf("expected error '%s', got none", u.err)
} else if u.err != "" && gotErr != nil && gotErr.Error() != u.err {
t.Fatalf("expected error '%s', got '%s'", u.err, gotErr)
} else if gotStdout != u.stdout {
t.Fatalf("expected stdout '%s', got '%s'", u.stdout, gotStdout)
}
}
}
func TestCoreExists(t *testing.T) { func TestCoreExists(t *testing.T) {
var units = []struct { var units = []struct {
what string what string

View file

@ -1,6 +1,8 @@
package core package core
import "flag" import (
"flag"
)
type Options struct { type Options struct {
InterfaceName *string InterfaceName *string
@ -18,6 +20,7 @@ type Options struct {
MemProfile *string MemProfile *string
CapletsPath *string CapletsPath *string
Script *string Script *string
PcapBufSize *int
} }
func ParseOptions() (Options, error) { func ParseOptions() (Options, error) {
@ -37,6 +40,7 @@ func ParseOptions() (Options, error) {
MemProfile: flag.String("mem-profile", "", "Write memory profile to `file`."), MemProfile: flag.String("mem-profile", "", "Write memory profile to `file`."),
CapletsPath: flag.String("caplets-path", "", "Specify an alternative base path for caplets."), CapletsPath: flag.String("caplets-path", "", "Specify an alternative base path for caplets."),
Script: flag.String("script", "", "Load a session script."), Script: flag.String("script", "", "Load a session script."),
PcapBufSize: flag.Int("pcap-buf-size", -1, "PCAP buffer size, leave to 0 for the default value."),
} }
flag.Parse() flag.Parse()

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"strings"
"github.com/bettercap/bettercap/core" "github.com/bettercap/bettercap/core"
"github.com/bettercap/bettercap/network" "github.com/bettercap/bettercap/network"
@ -73,10 +74,18 @@ func (f LinuxFirewall) EnableForwarding(enabled bool) error {
func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []string) { func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []string) {
action := "-A" action := "-A"
destination := ""
if !enabled { if !enabled {
action = "-D" action = "-D"
} }
if strings.Count(r.DstAddress, ":") < 2 {
destination = r.DstAddress
} else {
destination = fmt.Sprintf("[%s]", r.DstAddress)
}
if r.SrcAddress == "" { if r.SrcAddress == "" {
cmdLine = []string{ cmdLine = []string{
"-t", "nat", "-t", "nat",
@ -85,7 +94,7 @@ func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []
"-p", r.Protocol, "-p", r.Protocol,
"--dport", fmt.Sprintf("%d", r.SrcPort), "--dport", fmt.Sprintf("%d", r.SrcPort),
"-j", "DNAT", "-j", "DNAT",
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort), "--to", fmt.Sprintf("%s:%d", destination, r.DstPort),
} }
} else { } else {
cmdLine = []string{ cmdLine = []string{
@ -96,7 +105,7 @@ func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []
"-d", r.SrcAddress, "-d", r.SrcAddress,
"--dport", fmt.Sprintf("%d", r.SrcPort), "--dport", fmt.Sprintf("%d", r.SrcPort),
"-j", "DNAT", "-j", "DNAT",
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort), "--to", fmt.Sprintf("%s:%d", destination, r.DstPort),
} }
} }
@ -107,6 +116,13 @@ func (f *LinuxFirewall) EnableRedirection(r *Redirection, enabled bool) error {
cmdLine := f.getCommandLine(r, enabled) cmdLine := f.getCommandLine(r, enabled)
rkey := r.String() rkey := r.String()
_, found := f.redirections[rkey] _, found := f.redirections[rkey]
cmd := ""
if strings.Count(r.DstAddress, ":") < 2 {
cmd = "iptables"
} else {
cmd = "ip6tables"
}
if enabled { if enabled {
if found { if found {
@ -116,9 +132,9 @@ func (f *LinuxFirewall) EnableRedirection(r *Redirection, enabled bool) error {
f.redirections[rkey] = r f.redirections[rkey] = r
// accept all // accept all
if _, err := core.Exec("iptables", []string{"-P", "FORWARD", "ACCEPT"}); err != nil { if _, err := core.Exec(cmd, []string{"-P", "FORWARD", "ACCEPT"}); err != nil {
return err return err
} else if _, err := core.Exec("iptables", cmdLine); err != nil { } else if _, err := core.Exec(cmd, cmdLine); err != nil {
return err return err
} }
} else { } else {
@ -128,7 +144,7 @@ func (f *LinuxFirewall) EnableRedirection(r *Redirection, enabled bool) error {
delete(f.redirections, r.String()) delete(f.redirections, r.String())
if _, err := core.Exec("iptables", cmdLine); err != nil { if _, err := core.Exec(cmd, cmdLine); err != nil {
return err return err
} }
} }

35
go.mod
View file

@ -1,13 +1,13 @@
module github.com/bettercap/bettercap module github.com/bettercap/bettercap
go 1.12 go 1.16
require ( require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/adrianmo/go-nmea v1.3.0 github.com/adrianmo/go-nmea v1.3.0
github.com/antchfx/jsonquery v1.1.4 github.com/antchfx/jsonquery v1.1.4
github.com/antchfx/xpath v1.1.11 // indirect github.com/antchfx/xpath v1.2.0 // indirect
github.com/bettercap/gatt v0.0.0-20210412143611-7a3c1c59fe92 github.com/bettercap/gatt v0.0.0-20210514133428-df6e615f2f67
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3 github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3
@ -15,7 +15,7 @@ require (
github.com/chzyer/logex v1.1.10 // indirect github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/dustin/go-humanize v1.0.0 github.com/dustin/go-humanize v1.0.0
github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4
github.com/elazarl/goproxy/ext v0.0.0-20210110162100-a92cc753f88e // indirect github.com/elazarl/goproxy/ext v0.0.0-20210110162100-a92cc753f88e // indirect
github.com/evilsocket/islazy v1.10.6 github.com/evilsocket/islazy v1.10.6
github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe
@ -24,34 +24,25 @@ require (
github.com/google/go-github v17.0.0+incompatible github.com/google/go-github v17.0.0+incompatible
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gopacket v1.1.19 github.com/google/gopacket v1.1.19
github.com/google/gousb v2.1.0+incompatible github.com/google/gousb v1.1.2
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/hashicorp/mdns v1.0.3 github.com/hashicorp/mdns v1.0.4
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b
github.com/jpillora/go-tld v1.1.1 github.com/jpillora/go-tld v1.1.1
github.com/koppacetic/go-gpsd v0.4.0 github.com/koppacetic/go-gpsd v0.4.0
github.com/kr/binarydist v0.1.0 // indirect github.com/kr/binarydist v0.1.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/malfunkt/iprange v0.9.0 github.com/malfunkt/iprange v0.9.0
github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.13 // indirect
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/miekg/dns v1.1.43
github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab // indirect
github.com/miekg/dns v1.1.41
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452
github.com/stretchr/testify v1.7.0 // indirect
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 // indirect
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
honnef.co/go/tools v0.0.0-2019.2.1 // indirect
) )

197
go.sum
View file

@ -1,38 +1,16 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/adrianmo/go-nmea v1.1.0 h1:0NILSj14nj6LvVQHo/afHbyPgGz5qvp5PM6jmMyAQzY=
github.com/adrianmo/go-nmea v1.1.0/go.mod h1:HHPxPAm2kmev+61qmkZh7xgZF/7qHtSpsWppip2Ipv8=
github.com/adrianmo/go-nmea v1.3.0 h1:BFrLRj/oIh+DYujIKpuQievq7X3NDHYq57kNgsfr2GY= github.com/adrianmo/go-nmea v1.3.0 h1:BFrLRj/oIh+DYujIKpuQievq7X3NDHYq57kNgsfr2GY=
github.com/adrianmo/go-nmea v1.3.0/go.mod h1:u8bPnpKt/D/5rll/5l9f6iDfeq5WZW0+/SXdkwix6Tg= github.com/adrianmo/go-nmea v1.3.0/go.mod h1:u8bPnpKt/D/5rll/5l9f6iDfeq5WZW0+/SXdkwix6Tg=
github.com/antchfx/jsonquery v0.0.0-20180821084212-a2896be8c82b h1:oREWiN8d6BYorETYz2PH2Kk0CtUdp0RETyab7ep4jNY=
github.com/antchfx/jsonquery v0.0.0-20180821084212-a2896be8c82b/go.mod h1:h7950pvPrUZzJIflNqsELgDQovTpPNa0rAHf8NwjegY=
github.com/antchfx/jsonquery v1.0.0 h1:1Yhk496SrCoY6fJkFZqpXEqbwOw5sFtLns9la4NoK3I=
github.com/antchfx/jsonquery v1.0.0/go.mod h1:h7950pvPrUZzJIflNqsELgDQovTpPNa0rAHf8NwjegY=
github.com/antchfx/jsonquery v1.1.4 h1:+OlFO3QS9wjU0MKx9MgHm5f6o6hdd4e9mUTp0wTjxlM= github.com/antchfx/jsonquery v1.1.4 h1:+OlFO3QS9wjU0MKx9MgHm5f6o6hdd4e9mUTp0wTjxlM=
github.com/antchfx/jsonquery v1.1.4/go.mod h1:cHs8r6Bymd8j6HI6Ej1IJbjahKvLBcIEh54dfmo+E9A= github.com/antchfx/jsonquery v1.1.4/go.mod h1:cHs8r6Bymd8j6HI6Ej1IJbjahKvLBcIEh54dfmo+E9A=
github.com/antchfx/xpath v1.0.0 h1:Q5gFgh2O40VTSwMOVbFE7nFNRBu3tS21Tn0KAWeEjtk=
github.com/antchfx/xpath v1.0.0/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
github.com/antchfx/xpath v1.1.0 h1:mJTvYpiHvxNQRD4Lbfin/FodHVCHh2a5KrOFr4ZxMOI=
github.com/antchfx/xpath v1.1.0/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
github.com/antchfx/xpath v1.1.7/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= github.com/antchfx/xpath v1.1.7/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk=
github.com/antchfx/xpath v1.1.10 h1:cJ0pOvEdN/WvYXxvRrzQH9x5QWKpzHacYO8qzCcDYAg= github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8=
github.com/antchfx/xpath v1.1.10/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNYhvtNk= github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/antchfx/xpath v1.1.11 h1:WOFtK8TVAjLm3lbgqeP0arlHpvCEeTANeWZ/csPpJkQ= github.com/bettercap/gatt v0.0.0-20210514133428-df6e615f2f67 h1:xzN6806c01hWTz8gjGsRjhOPlYj5/dNoZIR8CN9+O1c=
github.com/antchfx/xpath v1.1.11/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/bettercap/gatt v0.0.0-20210514133428-df6e615f2f67/go.mod h1:oafnPgaBI4gqJiYkueCyR4dqygiWGXTGOE0gmmAVeeQ=
github.com/bettercap/gatt v0.0.0-20190418085356-fac16c0ad797 h1:P9DK7Ij21WQAPFTUix8rblTVKDdwJEimCVO5foIr2ik=
github.com/bettercap/gatt v0.0.0-20190418085356-fac16c0ad797/go.mod h1:xbRFD+l8RcbQ3DscCiYX0dgEnXbwozZgm6oP2GXic+0=
github.com/bettercap/gatt v0.0.0-20191018133023-569d3d9372bb h1:GOaknHS3DCZcBbQRScDl6uecgkrkK7YFToIA5Uc6lHU=
github.com/bettercap/gatt v0.0.0-20191018133023-569d3d9372bb/go.mod h1:xbRFD+l8RcbQ3DscCiYX0dgEnXbwozZgm6oP2GXic+0=
github.com/bettercap/gatt v0.0.0-20210323182651-e1a2422767ff h1:P99kfm6Ll1/yNvxAl/j2vF6pDZZnbwG4ThZCIALWEXE=
github.com/bettercap/gatt v0.0.0-20210323182651-e1a2422767ff/go.mod h1:t65axQjKQ5V+fav0omkETW5+OGOOPjV8b7q63/GF79E=
github.com/bettercap/gatt v0.0.0-20210412143611-7a3c1c59fe92 h1:+cZAjtR7zFbFx5/Hoyxm7WKbhAZHvXqFj9C7oYQFj1s=
github.com/bettercap/gatt v0.0.0-20210412143611-7a3c1c59fe92/go.mod h1:oafnPgaBI4gqJiYkueCyR4dqygiWGXTGOE0gmmAVeeQ=
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb h1:JWAAJk4ny+bT3VrtcX+e7mcmWtWUeUM0xVcocSAUuWc= github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb h1:JWAAJk4ny+bT3VrtcX+e7mcmWtWUeUM0xVcocSAUuWc=
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb/go.mod h1:g6WiaSRgMTiChuk7jYyFSEtpgaw1F0wAsBfspG3bu0M= github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb/go.mod h1:g6WiaSRgMTiChuk7jYyFSEtpgaw1F0wAsBfspG3bu0M=
github.com/bettercap/readline v0.0.0-20180208083827-9cec905dd291 h1:6GtREdpf6N/trykGvhwfr0nyo3V/yncz0JvNbu+z7S8=
github.com/bettercap/readline v0.0.0-20180208083827-9cec905dd291/go.mod h1:03rWiUf60r1miMVzMEtgtkq7RdZniecZFw3/Zgvyxcs=
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf h1:pwGPRc5PIp4KCF9QbKn0iLVMhfigUMw4IzGZEZ81m1I= github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf h1:pwGPRc5PIp4KCF9QbKn0iLVMhfigUMw4IzGZEZ81m1I=
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf/go.mod h1:03rWiUf60r1miMVzMEtgtkq7RdZniecZFw3/Zgvyxcs= github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf/go.mod h1:03rWiUf60r1miMVzMEtgtkq7RdZniecZFw3/Zgvyxcs=
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3 h1:pC4ZAk7UtDIbrRKzMMiIL1TVkiKlgtgcJodqKB53Rl4= github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3 h1:pC4ZAk7UtDIbrRKzMMiIL1TVkiKlgtgcJodqKB53Rl4=
@ -49,27 +27,15 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f h1:8GDPb0tCY8LQ+OJ3dbHb5sA6YZWXFORQYZx5sdsTlMs= github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4 h1:lS3P5Nw3oPO05Lk2gFiYUOL3QPaH+fRoI1wFOc4G1UY=
github.com/elazarl/goproxy v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20210801061803-8e322dfb79c4/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484 h1:pEtiCjIXx3RvGjlUJuCNxNOw0MNblyR9Wi+vJGBFh+8=
github.com/elazarl/goproxy v0.0.0-20191011121108-aa519ddbe484/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d h1:rtM8HsT3NG37YPjz8sYSbUSdElP9lUsQENYzJDZDUBE=
github.com/elazarl/goproxy v0.0.0-20200809112317-0581fc3aee2d/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e h1:/cwV7t2xezilMljIftb7WlFtzGANRCnoOhPjtl2ifcs=
github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f h1:AUj1VoZUfhPhOPHULCQQDnGhRelpFWHMLhQVWDsS0v4=
github.com/elazarl/goproxy/ext v0.0.0-20190421051319-9d40249d3c2f/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/elazarl/goproxy/ext v0.0.0-20210110162100-a92cc753f88e h1:CQn2/8fi3kmpT9BTiHEELgdxAOQNVZc9GoPA4qnQzrs= github.com/elazarl/goproxy/ext v0.0.0-20210110162100-a92cc753f88e h1:CQn2/8fi3kmpT9BTiHEELgdxAOQNVZc9GoPA4qnQzrs=
github.com/elazarl/goproxy/ext v0.0.0-20210110162100-a92cc753f88e/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/elazarl/goproxy/ext v0.0.0-20210110162100-a92cc753f88e/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
github.com/evilsocket/islazy v1.10.4 h1:Z5373Kn5Gh2EWch1Tb/Qxb6vyQ7lw704bmKi7sY4Ecs=
github.com/evilsocket/islazy v1.10.4/go.mod h1:OrwQGYg3DuZvXUfmH+KIZDjwTCbrjy48T24TUpGqVVw=
github.com/evilsocket/islazy v1.10.6 h1:MFq000a1ByoumoJWlytqg0qon0KlBeUfPsDjY0hK0bo= github.com/evilsocket/islazy v1.10.6 h1:MFq000a1ByoumoJWlytqg0qon0KlBeUfPsDjY0hK0bo=
github.com/evilsocket/islazy v1.10.6/go.mod h1:OrwQGYg3DuZvXUfmH+KIZDjwTCbrjy48T24TUpGqVVw= github.com/evilsocket/islazy v1.10.6/go.mod h1:OrwQGYg3DuZvXUfmH+KIZDjwTCbrjy48T24TUpGqVVw=
github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe h1:8P+/htb3mwwpeGdJg69yBF/RofK7c6Fjz5Ypa/bTqbY= github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe h1:8P+/htb3mwwpeGdJg69yBF/RofK7c6Fjz5Ypa/bTqbY=
github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -78,217 +44,106 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY=
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/google/gopacket v1.1.18 h1:lum7VRA9kdlvBi7/v2p7/zcbkduHaCH/SVVyurs7OpY=
github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/gousb v0.0.0-20190525092738-2dc560e6bea3 h1:3RtjTHQgWbD7dsPreVSkA5/LGfNnAZyjOtDXhargyEE= github.com/google/gousb v1.1.2 h1:1BwarNB3inFTFhPgUEfah4hwOPuDz/49I0uX8XNginU=
github.com/google/gousb v0.0.0-20190525092738-2dc560e6bea3/go.mod h1:Tl4HdAs1ThE3gECkNwz+1MWicX6FXddhJEw7L8jRDiI= github.com/google/gousb v1.1.2/go.mod h1:GGWUkK0gAXDzxhwrzetW592aOmkkqSGcj5KLEgmCVUg=
github.com/google/gousb v0.0.0-20190812193832-18f4c1d8a750 h1:DVKHLo3yE4psTjD9aM2pY7EHoicaQbgmaxxvvHC6ZSM=
github.com/google/gousb v0.0.0-20190812193832-18f4c1d8a750/go.mod h1:Tl4HdAs1ThE3gECkNwz+1MWicX6FXddhJEw7L8jRDiI=
github.com/google/gousb v2.1.0+incompatible h1:ApzMDjF3FeO219QwWybJxYfFhXQzPLOEy0o+w9k5DNI=
github.com/google/gousb v2.1.0+incompatible/go.mod h1:Tl4HdAs1ThE3gECkNwz+1MWicX6FXddhJEw7L8jRDiI=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/gorilla/mux v1.7.2 h1:zoNxOV7WjqXptQOVngLmcSQgXmgk4NMz1HibBchjl/I=
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/mdns v1.0.1 h1:XFSOubp8KWB+Jd2PDyaX5xUd5bhSP/+pTDZVDMzZJM8= github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/mdns v1.0.3 h1:hPneYJlzSjxFBmUlnDGXRykxBZ++dQAJhU57gCO7TzI=
github.com/hashicorp/mdns v1.0.3/go.mod h1:P9sIDVQGUBr2GtS4qS2QCBdtgqP7TBt6d8looU5l5r4=
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b h1:IpLPmn6Re21F0MaV6Zsc5RdSE6KuoFpWmHiUSEs3PrE= github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b h1:IpLPmn6Re21F0MaV6Zsc5RdSE6KuoFpWmHiUSEs3PrE=
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b/go.mod h1:aA6DnFhALT3zH0y+A39we+zbrdMC2N0X/q21e6FI0LU= github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b/go.mod h1:aA6DnFhALT3zH0y+A39we+zbrdMC2N0X/q21e6FI0LU=
github.com/jpillora/go-tld v0.0.0-20190202073305-f16ca3b7b383 h1:/ODEnccTd4m/1YbCDCZBIoo+W1BC+PjOzvfX8y++b5s=
github.com/jpillora/go-tld v0.0.0-20190202073305-f16ca3b7b383/go.mod h1:7H/4k+TVAFSXCq+KcvelJ5hClsXnabjF52BLYqgaqcQ=
github.com/jpillora/go-tld v1.0.0 h1:W0Wz3fYT9WCDNJXcXc58uV7sriLnVeELeOU5MP5X42M=
github.com/jpillora/go-tld v1.0.0/go.mod h1:kitBxOF//DR5FxYeIGw+etdiiTIq5S7bx0dwy1GUNAk=
github.com/jpillora/go-tld v1.1.1 h1:P1ZwtKDHBYYUl235R/D64cdBARfGYzEy1Hg2Ikir3FQ= github.com/jpillora/go-tld v1.1.1 h1:P1ZwtKDHBYYUl235R/D64cdBARfGYzEy1Hg2Ikir3FQ=
github.com/jpillora/go-tld v1.1.1/go.mod h1:kitBxOF//DR5FxYeIGw+etdiiTIq5S7bx0dwy1GUNAk= github.com/jpillora/go-tld v1.1.1/go.mod h1:kitBxOF//DR5FxYeIGw+etdiiTIq5S7bx0dwy1GUNAk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/koppacetic/go-gpsd v0.4.0 h1:/T3cRvi1ZsWbxCZPB9pPor0HjIw3HuD+MSvaxV5QqQ8= github.com/koppacetic/go-gpsd v0.4.0 h1:/T3cRvi1ZsWbxCZPB9pPor0HjIw3HuD+MSvaxV5QqQ8=
github.com/koppacetic/go-gpsd v0.4.0/go.mod h1:mhcLuh9X++WHepbL3jEmEwnx1OkQDepZMihv12RO4qk= github.com/koppacetic/go-gpsd v0.4.0/go.mod h1:mhcLuh9X++WHepbL3jEmEwnx1OkQDepZMihv12RO4qk=
github.com/kr/binarydist v0.1.0 h1:6kAoLA9FMMnNGSehX0s1PdjbEaACznAv/W219j2uvyo= github.com/kr/binarydist v0.1.0 h1:6kAoLA9FMMnNGSehX0s1PdjbEaACznAv/W219j2uvyo=
github.com/kr/binarydist v0.1.0/go.mod h1:DY7S//GCoz1BCd0B0EVrinCKAZN3pXe+MDaIZbXQVgM= github.com/kr/binarydist v0.1.0/go.mod h1:DY7S//GCoz1BCd0B0EVrinCKAZN3pXe+MDaIZbXQVgM=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/malfunkt/iprange v0.9.0 h1:VCs0PKLUPotNVQTpVNszsut4lP7OCGNBwX+lOYBrnVQ= github.com/malfunkt/iprange v0.9.0 h1:VCs0PKLUPotNVQTpVNszsut4lP7OCGNBwX+lOYBrnVQ=
github.com/malfunkt/iprange v0.9.0/go.mod h1:TRGqO/f95gh3LOndUGTL46+W0GXA91WTqyZ0Quwvt4U= github.com/malfunkt/iprange v0.9.0/go.mod h1:TRGqO/f95gh3LOndUGTL46+W0GXA91WTqyZ0Quwvt4U=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b h1:r12blE3QRYlW1WBiBEe007O6NrTb/P54OjR5d4WLEGk= github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b h1:r12blE3QRYlW1WBiBEe007O6NrTb/P54OjR5d4WLEGk=
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b/go.mod h1:p4K2+UAoap8Jzsadsxc0KG0OZjmmCthTPUyZqAVkjBY= github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b/go.mod h1:p4K2+UAoap8Jzsadsxc0KG0OZjmmCthTPUyZqAVkjBY=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab h1:n8cgpHzJ5+EDyDri2s/GC7a9+qK3/YEGnBsd0uS/8PY= github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab h1:n8cgpHzJ5+EDyDri2s/GC7a9+qK3/YEGnBsd0uS/8PY=
github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab/go.mod h1:y1pL58r5z2VvAjeG1VLGc8zOQgSOzbKN7kMHPvFXJ+8= github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab/go.mod h1:y1pL58r5z2VvAjeG1VLGc8zOQgSOzbKN7kMHPvFXJ+8=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.14 h1:wkQWn9wIp4mZbwW8XV6Km6owkvRPbOiV004ZM2CkGvA=
github.com/miekg/dns v1.1.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.22 h1:Jm64b3bO9kP43ddLjL2EY3Io6bmy1qGb9Xxz6TqS6rc=
github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.31 h1:sJFOl9BgwbYAWOGEwr61FU28pqsBNdpRBnhGXtO06Oo=
github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4= github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452 h1:ewTtJ72GFy2e0e8uyiDwMG3pKCS5mBh+hdSTYsPKEP8=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac h1:kYPjbEN6YPYWWHI6ky1J813KzIq/8+Wg4TO4xU7A/KU=
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb h1:EavwSqheIJl3nb91HhkL73DwnT2Fk8W3yM7T7TuLZvA= github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64 h1:l/T7dYuJEQZOwVOpjIXr1180aM9PZL/d1MnMVIxefX4=
github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb/go.mod h1:I0ZT9x8wStY6VOxtNOrLpnDURFs7HS0z1e1vhuKUEVc= github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64/go.mod h1:Q1NAJOuRdQCqN/VIWdnaaEhV8LpeO2rtlBP7/iDJNII=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190310074541-c10a0554eabf/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190310074541-c10a0554eabf/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 h1:p9xBe/w/OzkeYVKm234g55gMdD1nSIooTir5kV11kfA=
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321 h1:lleNcKRbcaC8MqgLwghIkzZ2JBQAb7QQ9MiwRt1BisA=
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1 h1:4qWs8cYYH6PoEFy4dfhDFgoMGkwAcETd+MmPdCPMzUc=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191018095205-727590c5006e h1:ZtoklVMHQy6BFRHkbG6JzK+S6rX82//Yeok1vMlizfQ=
golang.org/x/sys v0.0.0-20191018095205-727590c5006e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46 h1:V066+OYJ66oTjnhm4Yrn7SXIwSCiDQJxpBxmvqb1N1c=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac h1:MQEvx39qSf8vyrx3XRaOe+j1UDIzKwkYOVObRgGPVqI=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-2019.2.1 h1:fW1wbZIKRbRK56ETe5SYloH5SdLzhXOFet2KlpRKDqg=
honnef.co/go/tools v0.0.0-2019.2.1/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=

View file

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"encoding/base64" "encoding/base64"
"github.com/robertkrimen/otto" "github.com/robertkrimen/otto"
) )
@ -13,6 +14,7 @@ func btoa(call otto.FunctionCall) otto.Value {
if err != nil { if err != nil {
return ReportError("Could not convert to string: %s", varValue) return ReportError("Could not convert to string: %s", varValue)
} }
return v return v
} }
@ -21,10 +23,12 @@ func atob(call otto.FunctionCall) otto.Value {
if err != nil { if err != nil {
return ReportError("Could not decode string: %s", call.Argument(0).String()) return ReportError("Could not decode string: %s", call.Argument(0).String())
} }
v, err := otto.ToValue(string(varValue)) v, err := otto.ToValue(string(varValue))
if err != nil { if err != nil {
return ReportError("Could not convert to string: %s", varValue) return ReportError("Could not convert to string: %s", varValue)
} }
return v return v
} }

View file

@ -3,12 +3,13 @@ package js
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/robertkrimen/otto"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
"github.com/robertkrimen/otto"
) )
type httpPackage struct { type httpPackage struct {
@ -26,7 +27,10 @@ func (c httpPackage) Encode(s string) string {
return url.QueryEscape(s) return url.QueryEscape(s)
} }
func (c httpPackage) Request(method string, uri string, headers map[string]string, form map[string]string, json string) httpResponse { func (c httpPackage) Request(method string, uri string,
headers map[string]string,
form map[string]string,
json string) httpResponse {
var reader io.Reader var reader io.Reader
if form != nil { if form != nil {

View file

@ -3,7 +3,6 @@ package js
import ( import (
"github.com/evilsocket/islazy/log" "github.com/evilsocket/islazy/log"
"github.com/evilsocket/islazy/plugin" "github.com/evilsocket/islazy/plugin"
"github.com/robertkrimen/otto" "github.com/robertkrimen/otto"
) )

View file

@ -44,7 +44,7 @@ func NewAnyProxy(s *session.Session) *AnyProxy {
mod.AddParam(session.NewStringParameter("any.proxy.dst_address", mod.AddParam(session.NewStringParameter("any.proxy.dst_address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, "",
"Address where the proxy is listening.")) "Address where the proxy is listening."))
mod.AddParam(session.NewIntParameter("any.proxy.dst_port", mod.AddParam(session.NewIntParameter("any.proxy.dst_port",

View file

@ -3,6 +3,7 @@ package arp_spoof
import ( import (
"bytes" "bytes"
"net" "net"
"strings"
"sync" "sync"
"time" "time"
@ -22,6 +23,7 @@ type ArpSpoofer struct {
fullDuplex bool fullDuplex bool
internal bool internal bool
ban bool ban bool
skipRestore bool
waitGroup *sync.WaitGroup waitGroup *sync.WaitGroup
} }
@ -35,6 +37,7 @@ func NewArpSpoofer(s *session.Session) *ArpSpoofer {
ban: false, ban: false,
internal: false, internal: false,
fullDuplex: false, fullDuplex: false,
skipRestore: false,
waitGroup: &sync.WaitGroup{}, waitGroup: &sync.WaitGroup{},
} }
@ -52,6 +55,20 @@ func NewArpSpoofer(s *session.Session) *ArpSpoofer {
"false", "false",
"If true, both the targets and the gateway will be attacked, otherwise only the target (if the router has ARP spoofing protections in place this will make the attack fail).")) "If true, both the targets and the gateway will be attacked, otherwise only the target (if the router has ARP spoofing protections in place this will make the attack fail)."))
noRestore := session.NewBoolParameter("arp.spoof.skip_restore",
"false",
"If set to true, targets arp cache won't be restored when spoofing is stopped.")
mod.AddObservableParam(noRestore, func(v string) {
if strings.ToLower(v) == "true" || v == "1" {
mod.skipRestore = true
mod.Warning("arp cache restoration after spoofing disabled")
} else {
mod.skipRestore = false
mod.Debug("arp cache restoration after spoofing enabled")
}
})
mod.AddHandler(session.NewModuleHandler("arp.spoof on", "", mod.AddHandler(session.NewModuleHandler("arp.spoof on", "",
"Start ARP spoofer.", "Start ARP spoofer.",
func(args []string) error { func(args []string) error {
@ -171,6 +188,7 @@ func (mod *ArpSpoofer) Start() error {
} }
func (mod *ArpSpoofer) unSpoof() error { func (mod *ArpSpoofer) unSpoof() error {
if !mod.skipRestore {
nTargets := len(mod.addresses) + len(mod.macs) nTargets := len(mod.addresses) + len(mod.macs)
mod.Info("restoring ARP cache of %d targets.", nTargets) mod.Info("restoring ARP cache of %d targets.", nTargets)
mod.arpSpoofTargets(mod.Session.Gateway.IP, mod.Session.Gateway.HW, false, false) mod.arpSpoofTargets(mod.Session.Gateway.IP, mod.Session.Gateway.HW, false, false)
@ -186,6 +204,9 @@ func (mod *ArpSpoofer) unSpoof() error {
} }
} }
} }
} else {
mod.Warning("arp cache restoration is disabled")
}
return nil return nil
} }
@ -260,7 +281,10 @@ func (mod *ArpSpoofer) arpSpoofTargets(saddr net.IP, smac net.HardwareAddr, chec
} }
} }
for ip, mac := range mod.getTargets(probe) { if targets := mod.getTargets(probe); len(targets) == 0 {
mod.Warning("could not find spoof targets")
} else {
for ip, mac := range targets {
if check_running && !mod.Running() { if check_running && !mod.Running() {
return return
} else if mod.isWhitelisted(ip, mac) { } else if mod.isWhitelisted(ip, mac) {
@ -305,4 +329,5 @@ func (mod *ArpSpoofer) arpSpoofTargets(saddr net.IP, smac net.HardwareAddr, chec
} }
} }
} }
}
} }

View file

@ -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
} }

View file

@ -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

View file

@ -2,12 +2,13 @@ package events_stream
import ( import (
"fmt" "fmt"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/session"
"io" "io"
"os" "os"
"strings" "strings"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/session"
"github.com/bettercap/bettercap/modules/net_sniff" "github.com/bettercap/bettercap/modules/net_sniff"
"github.com/bettercap/bettercap/modules/syn_scan" "github.com/bettercap/bettercap/modules/syn_scan"
@ -119,6 +120,8 @@ func (mod *EventsStream) Render(output io.Writer, e session.Event) {
mod.viewBLEEvent(output, e) mod.viewBLEEvent(output, e)
} else if strings.HasPrefix(e.Tag, "hid.") { } else if strings.HasPrefix(e.Tag, "hid.") {
mod.viewHIDEvent(output, e) mod.viewHIDEvent(output, e)
} else if strings.HasPrefix(e.Tag, "gps.") {
mod.viewGPSEvent(output, e)
} else if strings.HasPrefix(e.Tag, "mod.") { } else if strings.HasPrefix(e.Tag, "mod.") {
mod.viewModuleEvent(output, e) mod.viewModuleEvent(output, e)
} else if strings.HasPrefix(e.Tag, "net.sniff.") { } else if strings.HasPrefix(e.Tag, "net.sniff.") {
@ -129,7 +132,7 @@ func (mod *EventsStream) Render(output io.Writer, e session.Event) {
mod.viewUpdateEvent(output, e) mod.viewUpdateEvent(output, e)
} else if e.Tag == "gateway.change" { } else if e.Tag == "gateway.change" {
mod.viewGatewayEvent(output, e) mod.viewGatewayEvent(output, e)
} else if e.Tag != "tick" { } else if e.Tag != "tick" && e.Tag != "session.started" && e.Tag != "session.stopped" {
fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e) fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e)
} }
} }

View file

@ -0,0 +1,24 @@
package events_stream
import (
"fmt"
"io"
"github.com/bettercap/bettercap/session"
"github.com/evilsocket/islazy/tui"
)
func (mod *EventsStream) viewGPSEvent(output io.Writer, e session.Event) {
if e.Tag == "gps.new" {
gps := e.Data.(session.GPS)
fmt.Fprintf(output, "[%s] [%s] latitude:%f longitude:%f quality:%s satellites:%d altitude:%f\n",
e.Time.Format(mod.timeFormat),
tui.Green(e.Tag),
gps.Latitude,
gps.Longitude,
gps.FixQuality,
gps.NumSatellites,
gps.Altitude)
}
}

View file

@ -138,16 +138,7 @@ func (mod *GPS) readFromSerial() {
if line, err := mod.readLine(); err == nil { if line, err := mod.readLine(); err == nil {
if s, err := nmea.Parse(line); err == nil { if s, err := nmea.Parse(line); err == nil {
// http://aprs.gids.nl/nmea/#gga // http://aprs.gids.nl/nmea/#gga
if m, ok := s.(nmea.GNGGA); ok { if m, ok := s.(nmea.GGA); ok {
mod.Session.GPS.Updated = time.Now()
mod.Session.GPS.Latitude = m.Latitude
mod.Session.GPS.Longitude = m.Longitude
mod.Session.GPS.FixQuality = m.FixQuality
mod.Session.GPS.NumSatellites = m.NumSatellites
mod.Session.GPS.HDOP = m.HDOP
mod.Session.GPS.Altitude = m.Altitude
mod.Session.GPS.Separation = m.Separation
} else if m, ok := s.(nmea.GPGGA); ok {
mod.Session.GPS.Updated = time.Now() mod.Session.GPS.Updated = time.Now()
mod.Session.GPS.Latitude = m.Latitude mod.Session.GPS.Latitude = m.Latitude
mod.Session.GPS.Longitude = m.Longitude mod.Session.GPS.Longitude = m.Longitude
@ -156,6 +147,8 @@ func (mod *GPS) readFromSerial() {
mod.Session.GPS.HDOP = m.HDOP mod.Session.GPS.HDOP = m.HDOP
mod.Session.GPS.Altitude = m.Altitude mod.Session.GPS.Altitude = m.Altitude
mod.Session.GPS.Separation = m.Separation mod.Session.GPS.Separation = m.Separation
mod.Session.Events.Add("gps.new", mod.Session.GPS)
} }
} else { } else {
mod.Debug("error parsing line '%s': %s", line, err) mod.Debug("error parsing line '%s': %s", line, err)
@ -173,6 +166,8 @@ func (mod *GPS) runFromGPSD() {
mod.Session.GPS.Longitude = report.Lon mod.Session.GPS.Longitude = report.Lon
mod.Session.GPS.FixQuality = ModeInfo[report.Mode] mod.Session.GPS.FixQuality = ModeInfo[report.Mode]
mod.Session.GPS.Altitude = report.Alt mod.Session.GPS.Altitude = report.Alt
mod.Session.Events.Add("gps.new", mod.Session.GPS)
}) })
mod.gpsd.Subscribe("SKY", func(r interface{}) { mod.gpsd.Subscribe("SKY", func(r interface{}) {

View file

@ -116,13 +116,7 @@ func (p *HTTPProxy) onResponseFilter(res *http.Response, ctx *goproxy.ProxyCtx)
if jsres != nil { if jsres != nil {
// the response has been changed by the script // the response has been changed by the script
p.logResponseAction(res.Request, jsres) p.logResponseAction(res.Request, jsres)
raw, err := ioutil.ReadAll(jsres.ToResponse(res.Request).Body) return jsres.ToResponse(res.Request)
if err == nil {
html := string(raw)
res.Header.Set("Content-Length", strconv.Itoa(len(html)))
// reset the response body to the original unread state
res.Body = ioutil.NopCloser(strings.NewReader(html))
}
} }
} }

View file

@ -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"
@ -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"] {

View file

@ -32,7 +32,9 @@ func NewNDPSpoofer(s *session.Session) *NDPSpoofer {
mod.AddParam(session.NewStringParameter("ndp.spoof.targets", "", "", mod.AddParam(session.NewStringParameter("ndp.spoof.targets", "", "",
"Comma separated list of IPv6 victim addresses.")) "Comma separated list of IPv6 victim addresses."))
mod.AddParam(session.NewStringParameter("ndp.spoof.neighbour", "fe80::1", "", mod.AddParam(session.NewStringParameter("ndp.spoof.neighbour",
"fe80::1",
session.IPv6Validator,
"Neighbour IPv6 address to spoof, clear to disable NA.")) "Neighbour IPv6 address to spoof, clear to disable NA."))
mod.AddParam(session.NewStringParameter("ndp.spoof.prefix", "d00d::", "", mod.AddParam(session.NewStringParameter("ndp.spoof.prefix", "d00d::", "",
@ -122,7 +124,7 @@ func (mod *NDPSpoofer) Start() error {
} }
return mod.SetRunning(true, func() { return mod.SetRunning(true, func() {
mod.Info("ndp spoofer started - neighbour=%s prefix=%s", mod.neighbour, mod.prefix) mod.Info("ndp spoofer started - targets=%s neighbour=%s prefix=%s", mod.addresses, mod.neighbour, mod.prefix)
mod.waitGroup.Add(1) mod.waitGroup.Add(1)
defer mod.waitGroup.Done() defer mod.waitGroup.Done()
@ -179,6 +181,8 @@ func (mod *NDPSpoofer) getTargets(probe bool) map[string]net.HardwareAddr {
// do we have this ip mac address? // do we have this ip mac address?
if hw, err := mod.Session.FindMAC(ip, probe); err == nil { if hw, err := mod.Session.FindMAC(ip, probe); err == nil {
targets[ip.String()] = hw targets[ip.String()] = hw
} else {
mod.Info("couldn't get MAC for ip=%s, put it into the neighbour table manually e.g. ping -6")
} }
} }

View file

@ -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 {

View file

@ -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

View file

@ -9,6 +9,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime"
"github.com/bettercap/bettercap/session" "github.com/bettercap/bettercap/session"
@ -29,6 +30,13 @@ type UIModule struct {
uiPath string uiPath string
} }
func getDefaultInstallBase() string {
if runtime.GOOS == "windows" {
return filepath.Join(os.Getenv("ALLUSERSPROFILE"), "bettercap")
}
return "/usr/local/share/bettercap/"
}
func NewUIModule(s *session.Session) *UIModule { func NewUIModule(s *session.Session) *UIModule {
mod := &UIModule{ mod := &UIModule{
SessionModule: session.NewSessionModule("ui", s), SessionModule: session.NewSessionModule("ui", s),
@ -36,7 +44,7 @@ func NewUIModule(s *session.Session) *UIModule {
} }
mod.AddParam(session.NewStringParameter("ui.basepath", mod.AddParam(session.NewStringParameter("ui.basepath",
"/usr/local/share/bettercap/", getDefaultInstallBase(),
"", "",
"UI base installation path.")) "UI base installation path."))

View file

@ -54,6 +54,8 @@ type WiFiModule struct {
assocSilent bool assocSilent bool
assocOpen bool assocOpen bool
assocAcquired bool assocAcquired bool
csaSilent bool
fakeAuthSilent bool
filterProbeSTA *regexp.Regexp filterProbeSTA *regexp.Regexp
filterProbeAP *regexp.Regexp filterProbeAP *regexp.Regexp
apRunning bool apRunning bool
@ -88,6 +90,8 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
assocSilent: false, assocSilent: false,
assocOpen: false, assocOpen: false,
assocAcquired: false, assocAcquired: false,
csaSilent: false,
fakeAuthSilent: false,
showManuf: false, showManuf: false,
shakesAggregate: true, shakesAggregate: true,
writes: &sync.WaitGroup{}, writes: &sync.WaitGroup{},
@ -215,6 +219,50 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
mod.AddHandler(probe) mod.AddHandler(probe)
channelSwitchAnnounce := session.NewModuleHandler("wifi.channel_switch_announce bssid channel ", `wifi\.channel_switch_announce ((?:[a-fA-F0-9:]{11,}))\s+((?:[0-9]+))`,
"Start a 802.11 channel hop attack, all client will be force to change the channel lead to connection down.",
func(args []string) error {
bssid, err := net.ParseMAC(args[0])
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)
}
return mod.startCSA(bssid, int8(channel))
})
channelSwitchAnnounce.Complete("wifi.channel_switch_announce", s.WiFiCompleterFull)
mod.AddHandler(channelSwitchAnnounce)
fakeAuth := session.NewModuleHandler("wifi.fake_auth bssid client", `wifi\.fake_auth ((?:[a-fA-F0-9:]{11,}))\s+((?:[a-fA-F0-9:]{11,}))`,
"send an fake authentication with client mac to ap lead to client disconnect",
func(args []string) error {
bssid, err := net.ParseMAC(args[0])
if err != nil {
return err
}
client, err := net.ParseMAC(args[1])
if err != nil {
return err
}
return mod.startFakeAuth(bssid, client)
})
fakeAuth.Complete("wifi.fake_auth", s.WiFiCompleterFull)
mod.AddHandler(fakeAuth)
mod.AddParam(session.NewBoolParameter("wifi.channel_switch_announce.silent",
"false",
"If true, messages from wifi.channel_switch_announce will be suppressed."))
mod.AddParam(session.NewBoolParameter("wifi.fake_auth.silent",
"false",
"If true, messages from wifi.fake_auth will be suppressed."))
mod.AddParam(session.NewStringParameter("wifi.deauth.skip", mod.AddParam(session.NewStringParameter("wifi.deauth.skip",
"", "",
"", "",
@ -502,60 +550,40 @@ func (mod *WiFiModule) Configure() error {
if mod.txPower > 0 { if mod.txPower > 0 {
if err := network.SetInterfaceTxPower(ifName, mod.txPower); err != nil { if err := network.SetInterfaceTxPower(ifName, mod.txPower); err != nil {
mod.Warning("could not set interface %s txpower to %d, 'Set Tx Power' requests not supported", ifName, mod.txPower) mod.Warning("could not set interface %s txpower to %d, 'Set Tx Power' requests not supported: %v", ifName, mod.txPower, err)
} else { } else {
mod.Debug("interface %s txpower set to %d", ifName, mod.txPower) mod.Debug("interface %s txpower set to %d", ifName, mod.txPower)
} }
} }
setRFMonMaybeFatal := false
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)
}
} 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)
}
/* /*
* We don't want to pcap.BlockForever otherwise pcap_close(handle) * We don't want to pcap.BlockForever otherwise pcap_close(handle)
* could hang waiting for a timeout to expire ... * could hang waiting for a timeout to expire ...
*/ */
readTimeout := 500 * time.Millisecond opts := network.CAPTURE_DEFAULTS
if err = ihandle.SetTimeout(readTimeout); err != nil { opts.Timeout = 500 * time.Millisecond
return fmt.Errorf("error while setting timeout: %s", err) opts.Monitor = true
} else if mod.handle, err = ihandle.Activate(); err != nil {
if retry == 0 && err.Error() == ErrIfaceNotUp { for retry := 0; ; retry++ {
mod.Debug("interface %s is down, bringing it up ...", ifName) 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 { if err := network.ActivateInterface(ifName); err != nil {
return err return err
} }
continue continue
} } else if !opts.Monitor {
if setRFMonMaybeFatal { // second fatal error, just bail
return fmt.Errorf("error while activating handle: %s", err) return fmt.Errorf("error while activating handle: %s", err)
} else { } else {
// 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!")) mod.Warning("error while activating handle: %s, %s", err, tui.Bold("interface might already be monitoring. retrying!"))
setRFMonMaybeFatal = true opts.Monitor = false
continue
} }
} }
break
}
} }
if err, mod.skipBroken = mod.BoolParam("wifi.skip-broken"); err != nil { if err, mod.skipBroken = mod.BoolParam("wifi.skip-broken"); err != nil {

86
modules/wifi/wifi_csa.go Normal file
View file

@ -0,0 +1,86 @@
package wifi
import (
"bytes"
"fmt"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/packets"
"github.com/google/gopacket/layers"
"net"
)
func (mod *WiFiModule) isCSASilent() bool {
if err, is := mod.BoolParam("wifi.channel_switch_announce.silent"); err != nil {
mod.Warning("%v", err)
} else {
mod.csaSilent = is
}
return mod.csaSilent
}
func (mod *WiFiModule) sendBeaconWithCSAPacket(ap *network.AccessPoint, toChan int8) {
ssid := ap.ESSID()
if ssid == "<hidden>" {
ssid = ""
}
hw, _ := net.ParseMAC(ap.BSSID())
for seq := uint16(0); seq < 256 && mod.Running(); seq++ {
if err, pkt := packets.NewDot11Beacon(packets.Dot11ApConfig{
SSID: ssid,
BSSID: hw,
Channel: ap.Channel,
Encryption: false,
SpectrumManagement: true,
}, 0, packets.Dot11Info(layers.Dot11InformationElementIDSwitchChannelAnnounce, []byte{0, byte(toChan), 1})); err != nil {
mod.Error("could not create beacon packet: %s", err)
continue
} else {
mod.injectPacket(pkt)
}
}
}
func (mod *WiFiModule) startCSA(to net.HardwareAddr, toChan int8) error {
// if not already running, temporarily enable the pcap handle
// for packet injection
if !mod.Running() {
if err := mod.Configure(); err != nil {
return err
}
defer mod.handle.Close()
}
var ap *network.AccessPoint = nil
for _, _ap := range mod.Session.WiFi.List() {
if bytes.Equal(_ap.HW, to) {
ap = _ap
}
}
if ap == nil {
return fmt.Errorf("%s is an unknown BSSID", to.String())
}
mod.writes.Add(1)
go func() {
defer mod.writes.Done()
if mod.Running() {
logger := mod.Info
if mod.isCSASilent() {
logger = mod.Debug
}
logger("channel hop attack in AP %s (channel:%d encryption:%s), hop to channel %d ", ap.ESSID(), ap.Channel, ap.Encryption, toChan)
// send the beacon frame with channel switch announce element id
mod.onChannel(ap.Channel, func() {
mod.sendBeaconWithCSAPacket(ap, toChan)
})
}
}()
return nil
}

View file

@ -0,0 +1,71 @@
package wifi
import (
"bytes"
"fmt"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/packets"
"net"
)
func (mod *WiFiModule) isFakeAuthSilent() bool {
if err, is := mod.BoolParam("wifi.fake_auth.silent"); err != nil {
mod.Warning("%v", err)
} else {
mod.csaSilent = is
}
return mod.csaSilent
}
func(mod *WiFiModule)sendFakeAuthPacket(bssid,client net.HardwareAddr){
err,pkt:=packets.NewDot11Auth(client,bssid,0)
if err!=nil{
mod.Error("could not create authentication packet: %s", err)
return
}
for i:=0;i<32;i++{
mod.injectPacket(pkt)
}
}
func (mod *WiFiModule) startFakeAuth(bssid,client net.HardwareAddr) error {
// if not already running, temporarily enable the pcap handle
// for packet injection
if !mod.Running() {
if err := mod.Configure(); err != nil {
return err
}
defer mod.handle.Close()
}
var ap *network.AccessPoint = nil
for _, _ap := range mod.Session.WiFi.List() {
if bytes.Equal(_ap.HW, bssid) {
ap = _ap
}
}
if ap == nil {
return fmt.Errorf("%s is an unknown BSSID", bssid.String())
}
mod.writes.Add(1)
go func() {
defer mod.writes.Done()
if mod.Running() {
logger := mod.Info
if mod.isFakeAuthSilent() {
logger = mod.Debug
}
logger("fake authentication attack in AP: %s client: %s", ap.ESSID(), client.String())
// send the beacon frame with channel switch announce element id
mod.onChannel(ap.Channel, func() {
mod.sendFakeAuthPacket(bssid,client)
})
}
}()
return nil
}

View file

@ -29,11 +29,19 @@ const (
var ( var (
BroadcastHw = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} BroadcastHw = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
IPv4Validator = regexp.MustCompile(`^[0-9\.]+/?\d*$`) IPv4BlockValidator = regexp.MustCompile(`^` +
IPv4RangeValidator = regexp.MustCompile(`^[0-9\.\-]+/?\d*$`) `(?:(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])\.){3}` +
MACValidator = regexp.MustCompile(`(?i)^[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}$`) `(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])` +
`/(?:3[0-2]|2[0-9]|[1]?[0-9])` + `$`)
IPv4RangeValidator = regexp.MustCompile(`^` +
`(?:(?:(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])-)?(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])\.){3}` +
`(?:(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])-)?(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])` + `$`)
IPv4Validator = regexp.MustCompile(`^` +
`(?:(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])\.){3}` +
`(?:25[0-5]|2[0-4][0-9]|[1][0-9]{2}|[1-9]?[0-9])` + `$`)
MACValidator = regexp.MustCompile(`(?i)^(?:[a-f0-9]{2}:){5}[a-f0-9]{2}$`)
// lulz this sounds like a hamburger // lulz this sounds like a hamburger
macParser = regexp.MustCompile(`(?i)([a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2}:[a-f0-9]{1,2})`) macParser = regexp.MustCompile(`(?i)((?:[a-f0-9]{2}:){5}[a-f0-9]{2})`)
aliasParser = regexp.MustCompile(`(?i)([a-z_][a-z_0-9]+)`) aliasParser = regexp.MustCompile(`(?i)([a-z_][a-z_0-9]+)`)
) )
@ -247,7 +255,7 @@ func FindInterface(name string) (*Endpoint, error) {
// user did not provide an interface name, // user did not provide an interface name,
// return the first one with a valid ipv4 // return the first one with a valid ipv4
// address // address that does not loop back
for _, iface := range ifaces { for _, iface := range ifaces {
addrs, err := iface.Addrs() addrs, err := iface.Addrs()
if err != nil { if err != nil {
@ -257,7 +265,7 @@ func FindInterface(name string) (*Endpoint, error) {
for _, address := range addrs { for _, address := range addrs {
ip := address.String() ip := address.String()
if !strings.Contains(ip, "127.0.0.1") && IPv4Validator.MatchString(ip) { if !strings.HasPrefix(ip, "127.0.0.1") && IPv4BlockValidator.MatchString(ip) {
return buildEndpointFromInterface(iface) return buildEndpointFromInterface(iface)
} }
} }
@ -279,7 +287,11 @@ func SetWiFiRegion(region string) error {
func ActivateInterface(name string) error { func ActivateInterface(name string) error {
if out, err := core.Exec("ifconfig", []string{name, "up"}); err != nil { if out, err := core.Exec("ifconfig", []string{name, "up"}); err != nil {
if out != "" {
return fmt.Errorf("%v: %s", err, out)
} else {
return err return err
}
} else if out != "" { } else if out != "" {
return fmt.Errorf("unexpected output while activating interface %s: %s", name, out) return fmt.Errorf("unexpected output while activating interface %s: %s", name, out)
} }
@ -289,8 +301,7 @@ func ActivateInterface(name string) error {
func SetInterfaceTxPower(name string, txpower int) error { func SetInterfaceTxPower(name string, txpower int) error {
if core.HasBinary("iw") { if core.HasBinary("iw") {
Debug("SetInterfaceTxPower(%s, %d) iw based", name, txpower) Debug("SetInterfaceTxPower(%s, %d) iw based", name, txpower)
if _, err := core.Exec("iw", []string{"dev", name, "set", "txpower", "fixed", fmt.Sprintf("%d", if _, err := core.Exec("iw", []string{"dev", name, "set", "txpower", "fixed", fmt.Sprintf("%d", txpower)}); err != nil {
txpower)}); err != nil {
return err return err
} }
} else if core.HasBinary("iwconfig") { } else if core.HasBinary("iwconfig") {

View file

@ -73,7 +73,7 @@ func iwlistSupportedFrequencies(iface string) ([]int, error) {
} }
var iwPhyParser = regexp.MustCompile(`^\s*wiphy\s+(\d+)$`) var iwPhyParser = regexp.MustCompile(`^\s*wiphy\s+(\d+)$`)
var iwFreqParser = regexp.MustCompile(`^\s+\*\s+(\d+)\s+MHz.+$`) var iwFreqParser = regexp.MustCompile(`^\s+\*\s+(\d+)\s+MHz.+dBm.+$`)
func iwSupportedFrequencies(iface string) ([]int, error) { func iwSupportedFrequencies(iface string) ([]int, error) {
// first determine phy index // first determine phy index
@ -123,10 +123,12 @@ func iwSupportedFrequencies(iface string) ([]int, error) {
} }
func GetSupportedFrequencies(iface string) ([]int, error) { func GetSupportedFrequencies(iface string) ([]int, error) {
if core.HasBinary("iw") { // give priority to iwlist because of https://github.com/bettercap/bettercap/issues/881
return iwSupportedFrequencies(iface) if core.HasBinary("iwlist") {
} else if core.HasBinary("iwlist") {
return iwlistSupportedFrequencies(iface) return iwlistSupportedFrequencies(iface)
} else if core.HasBinary("iw") {
return iwSupportedFrequencies(iface)
} }
return nil, fmt.Errorf("no iw or iwlist binaries found in $PATH") return nil, fmt.Errorf("no iw or iwlist binaries found in $PATH")
} }

71
network/pcap.go Normal file
View 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)
}

View file

@ -23,6 +23,8 @@ func Dot11Freq2Chan(freq int) int {
return 14 return 14
} else if freq >= 5035 && freq <= 5865 { } else if freq >= 5035 && freq <= 5865 {
return ((freq - 5035) / 5) + 7 return ((freq - 5035) / 5) + 7
} else if freq >= 5875 && freq <= 5895 {
return 177
} }
return 0 return 0
} }
@ -34,6 +36,8 @@ func Dot11Chan2Freq(channel int) int {
return 2484 return 2484
} else if channel <= 173 { } else if channel <= 173 {
return ((channel - 7) * 5) + 5035 return ((channel - 7) * 5) + 5035
} else if channel == 177 {
return 5885
} }
return 0 return 0

View file

@ -6,26 +6,39 @@ import (
"github.com/evilsocket/islazy/data" "github.com/evilsocket/islazy/data"
) )
// Define test data for dot11 frequency <-> channel tests
type dot11pair struct {
frequency int
channel int
}
var dot11TestVector = []dot11pair{
{2472, 13},
{2484, 14},
{5825, 165},
{5885, 177},
}
func buildExampleWiFi() *WiFi { func buildExampleWiFi() *WiFi {
aliases := &data.UnsortedKV{} aliases := &data.UnsortedKV{}
return NewWiFi(buildExampleEndpoint(), aliases, func(ap *AccessPoint) {}, func(ap *AccessPoint) {}) return NewWiFi(buildExampleEndpoint(), aliases, func(ap *AccessPoint) {}, func(ap *AccessPoint) {})
} }
func TestDot11Freq2Chan(t *testing.T) { func TestDot11Freq2Chan(t *testing.T) {
exampleFreq := 2472 for _, entry := range dot11TestVector {
exp := 13 gotChannel := Dot11Freq2Chan(entry.frequency)
got := Dot11Freq2Chan(exampleFreq) if gotChannel != entry.channel {
if got != exp { t.Fatalf("expected '%v', got '%v'", entry.channel, gotChannel)
t.Fatalf("expected '%v', got '%v'", exp, got) }
} }
} }
func TestDot11Chan2Freq(t *testing.T) { func TestDot11Chan2Freq(t *testing.T) {
exampleChan := 13 for _, entry := range dot11TestVector {
exp := 2472 gotFrequency := Dot11Chan2Freq(entry.channel)
got := Dot11Chan2Freq(exampleChan) if gotFrequency != entry.frequency {
if got != exp { t.Fatalf("expected '%v', got '%v'", entry.frequency, gotFrequency)
t.Fatalf("expected '%v', got '%v'", exp, got) }
} }
} }

View file

@ -13,6 +13,7 @@ import (
var ( var (
openFlags = 1057 openFlags = 1057
wpaFlags = 1041 wpaFlags = 1041
specManFlag = 1<<8
durationID = uint16(0x013a) durationID = uint16(0x013a)
capabilityInfo = uint16(0x0411) capabilityInfo = uint16(0x0411)
listenInterval = uint16(3) listenInterval = uint16(3)
@ -41,6 +42,7 @@ type Dot11ApConfig struct {
BSSID net.HardwareAddr BSSID net.HardwareAddr
Channel int Channel int
Encryption bool Encryption bool
SpectrumManagement bool
} }
func Dot11Info(id layers.Dot11InformationElementID, info []byte) *layers.Dot11InformationElement { func Dot11Info(id layers.Dot11InformationElementID, info []byte) *layers.Dot11InformationElement {
@ -51,12 +53,14 @@ func Dot11Info(id layers.Dot11InformationElementID, info []byte) *layers.Dot11In
} }
} }
func NewDot11Beacon(conf Dot11ApConfig, seq uint16) (error, []byte) { func NewDot11Beacon(conf Dot11ApConfig, seq uint16, extendDot11Info ...*layers.Dot11InformationElement) (error, []byte) {
flags := openFlags flags := openFlags
if conf.Encryption { if conf.Encryption {
flags = wpaFlags flags = wpaFlags
} }
if conf.SpectrumManagement {
flags |= specManFlag
}
stack := []gopacket.SerializableLayer{ stack := []gopacket.SerializableLayer{
&layers.RadioTap{ &layers.RadioTap{
DBMAntennaSignal: int8(-10), DBMAntennaSignal: int8(-10),
@ -77,7 +81,9 @@ func NewDot11Beacon(conf Dot11ApConfig, seq uint16) (error, []byte) {
Dot11Info(layers.Dot11InformationElementIDRates, fakeApRates), Dot11Info(layers.Dot11InformationElementIDRates, fakeApRates),
Dot11Info(layers.Dot11InformationElementIDDSSet, []byte{byte(conf.Channel & 0xff)}), Dot11Info(layers.Dot11InformationElementIDDSSet, []byte{byte(conf.Channel & 0xff)}),
} }
for _, v := range extendDot11Info {
stack = append(stack, v)
}
if conf.Encryption { if conf.Encryption {
stack = append(stack, &layers.Dot11InformationElement{ stack = append(stack, &layers.Dot11InformationElement{
ID: layers.Dot11InformationElementIDRSNInfo, ID: layers.Dot11InformationElementIDRSNInfo,

View file

@ -177,14 +177,22 @@ func dot11ParseWPSVendorExtension(data []byte, info *map[string]string) string {
size := len(data) size := len(data)
for offset := 3; offset < size; { for offset := 3; offset < size; {
idByte := uint8(data[offset]) idByte := uint8(data[offset])
sizeByte := uint8(data[offset+1]) if next := offset + 1; next < size {
sizeByte := uint8(data[next])
if idByte == wpsVersion2ID { if idByte == wpsVersion2ID {
verByte := fmt.Sprintf("%x", data[offset+2]) if next = offset + 2; next < size {
verByte := fmt.Sprintf("%x", data[next])
(*info)["Version"] = wpsVersionDesc[verByte] (*info)["Version"] = wpsVersionDesc[verByte]
data = data[offset+3:] if next = offset + 3; next < size {
data = data[next:]
}
break break
} }
}
offset += int(sizeByte) + 2 offset += int(sizeByte) + 2
} else {
break
}
} }
} }
return hex.EncodeToString(data) return hex.EncodeToString(data)

View file

@ -5,7 +5,6 @@ import (
"strings" "strings"
"github.com/evilsocket/islazy/str" "github.com/evilsocket/islazy/str"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
) )

View file

@ -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
} }

View file

@ -1,10 +1,11 @@
package routing package routing
import ( import (
"github.com/bettercap/bettercap/core"
"github.com/evilsocket/islazy/str"
"regexp" "regexp"
"strings" "strings"
"github.com/bettercap/bettercap/core"
"github.com/evilsocket/islazy/str"
) )
var parser = regexp.MustCompile(`^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+).*$`) var parser = regexp.MustCompile(`^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+).*$`)

View file

@ -1,45 +1,78 @@
package routing package routing
import ( import (
"github.com/bettercap/bettercap/core"
"github.com/evilsocket/islazy/str"
"regexp" "regexp"
"strings" "strings"
"github.com/bettercap/bettercap/core"
"github.com/evilsocket/islazy/str"
) )
var parser = regexp.MustCompile(`^(.+)\sdev\s([^\s]+)\s(.+)$`) var (
routeHeadings []string
whitespaceParser = regexp.MustCompile(`\s+`)
)
func update() ([]Route, error) { func update() ([]Route, error) {
table = make([]Route, 0) table = make([]Route, 0)
for ip, inet := range map[RouteType]string{IPv4: "inet", IPv6: "inet6"} { output, err := core.Exec("netstat", []string{"-r", "-n", "-4", "-6"})
output, err := core.Exec("ip", []string{"-f", inet, "route"})
if err != nil { if err != nil {
return nil, err return nil, err
} }
// because entries are separated by whitespace
output = strings.ReplaceAll(output, "Next Hop", "Gateway")
for _, line := range strings.Split(output, "\n") { for _, line := range strings.Split(output, "\n") {
if line = str.Trim(line); len(line) > 0 { if line = str.Trim(line); len(line) != 0 {
matches := parser.FindStringSubmatch(line) parts := whitespaceParser.Split(line, -1)
if num := len(matches); num == 4 { if parts[0] == "Kernel" {
route := Route{ continue
Type: ip,
Destination: matches[1],
Device: matches[2],
Flags: matches[3],
Default: strings.Index(matches[1], "default ") == 0,
} }
if idx := strings.Index(route.Destination, " via "); idx >= 0 { if parts[0] == "Destination" {
route.Gateway = route.Destination[idx + len(" via "):] routeHeadings = parts
route.Destination = route.Destination[:idx] continue
}
route := Route{}
for i, s := range parts {
switch routeHeadings[i] {
case "Destination":
route.Destination = s
break
case "Flag":
route.Flags = s
break
case "Flags":
route.Flags = s
break
case "Gateway":
route.Gateway = s
break
case "If":
route.Device = s
break
case "Iface":
route.Device = s
break
case "Netif":
route.Device = s
break
}
}
route.Default = strings.Contains(route.Flags, "G")
if strings.ContainsRune(route.Destination, '.') || strings.ContainsRune(route.Gateway, '.') {
route.Type = IPv4
} else {
route.Type = IPv6
} }
table = append(table, route) table = append(table, route)
} }
} }
}
}
return table, nil return table, nil
} }

View file

@ -59,7 +59,7 @@ func NewIntParameter(name string, def_value string, desc string) *ModuleParam {
} }
func NewDecimalParameter(name string, def_value string, desc string) *ModuleParam { func NewDecimalParameter(name string, def_value string, desc string) *ModuleParam {
return NewModuleParameter(name, def_value, FLOAT, "^[\\d]+(\\.\\d+)?$", desc) return NewModuleParameter(name, def_value, FLOAT, `^[\-\+]?[\d]+(\.\d+)?$`, desc)
} }
func (p ModuleParam) validate(value string) (error, interface{}) { func (p ModuleParam) validate(value string) (error, interface{}) {

View file

@ -2,15 +2,17 @@ package session
import ( import (
"fmt" "fmt"
"github.com/bettercap/bettercap/caplets"
_ "github.com/bettercap/bettercap/js"
"github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/plugin"
"github.com/evilsocket/islazy/str"
"io/ioutil" "io/ioutil"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"github.com/bettercap/bettercap/caplets"
_ "github.com/bettercap/bettercap/js"
"github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/plugin"
"github.com/evilsocket/islazy/str"
) )
// require("telegram.js") // require("telegram.js")
@ -37,7 +39,7 @@ func preprocess(basePath string, code string, level int) (string, error) {
filepath.Join(caplets.InstallBase, fileName), filepath.Join(caplets.InstallBase, fileName),
} }
if strings.Contains(fileName, ".js") == false { if !strings.Contains(fileName, ".js") {
searchPaths = append(searchPaths, []string{ searchPaths = append(searchPaths, []string{
filepath.Join(basePath, fileName) + ".js", filepath.Join(basePath, fileName) + ".js",
filepath.Join(caplets.InstallBase, fileName) + ".js", filepath.Join(caplets.InstallBase, fileName) + ".js",

View file

@ -2,12 +2,18 @@ package session
import ( import (
"encoding/json" "encoding/json"
"io/ioutil"
"os"
"github.com/bettercap/bettercap/js" "github.com/bettercap/bettercap/js"
"github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/log" "github.com/evilsocket/islazy/log"
"github.com/robertkrimen/otto" "github.com/robertkrimen/otto"
) )
// see https://github.com/robertkrimen/otto/issues/213
var jsRuntime = otto.New()
func jsRunFunc(call otto.FunctionCall) otto.Value { func jsRunFunc(call otto.FunctionCall) otto.Value {
argv := call.ArgumentList argv := call.ArgumentList
argc := len(argv) argc := len(argv)
@ -67,15 +73,89 @@ func jsOnEventFunc(call otto.FunctionCall) otto.Value {
I.Events.Log(log.ERROR, "error serializing event %s: %v", event.Tag, err) I.Events.Log(log.ERROR, "error serializing event %s: %v", event.Tag, err)
} }
// lock vm // lock vm if ready and available
locked := false
if I.script != nil {
I.script.Lock() I.script.Lock()
locked = true
}
if _, err := cb.Call(otto.NullValue(), opaque); err != nil { if _, err := cb.Call(otto.NullValue(), opaque); err != nil {
I.Events.Log(log.ERROR, "error dispatching event %s: %v", event.Tag, err) I.Events.Log(log.ERROR, "error dispatching event %s: %v", event.Tag, err)
} }
// unlock vm if ready and available
if locked {
I.script.Unlock() I.script.Unlock()
} }
} }
}
}(filterExpr, cb) }(filterExpr, cb)
return js.NullValue return js.NullValue
} }
func jsSaveJSONFunc(call otto.FunctionCall) otto.Value {
argv := call.ArgumentList
argc := len(argv)
if argc != 2 {
return js.ReportError("saveJSON accepts one object and one string arguments")
} else if argv[0].IsObject() == false {
return js.ReportError("saveJSON accepts one object and one string arguments")
} else if argv[1].IsString() == false {
return js.ReportError("saveJSON accepts one object and one string arguments")
}
obj := argv[0]
if fileName, err := fs.Expand(argv[1].String()); err != nil {
return js.ReportError("can't expand '%s': %v", fileName, err)
} else if exp, err := obj.Export(); err != nil {
return js.ReportError("error exporting object: %v", err)
} else if raw, err := json.Marshal(exp); err != nil {
return js.ReportError("error serializing object: %v", err)
} else if err = ioutil.WriteFile(fileName, raw, os.ModePerm); err != nil {
return js.ReportError("error writing to '%s': %v", fileName, err)
}
return js.NullValue
}
func jsLoadJSONFunc(call otto.FunctionCall) otto.Value {
argv := call.ArgumentList
argc := len(argv)
if argc != 1 {
return js.ReportError("loadJSON accepts one string argument")
} else if argv[0].IsString() == false {
return js.ReportError("loadJSON accepts one string argument")
}
var obj interface{}
if fileName, err := fs.Expand(argv[0].String()); err != nil {
return js.ReportError("can't expand '%s': %v", fileName, err)
} else if rawData, err := ioutil.ReadFile(fileName); err != nil {
return js.ReportError("can't read '%s': %v", fileName, err)
} else if err = json.Unmarshal(rawData, &obj); err != nil {
return js.ReportError("can't parse '%s': %v", fileName, err)
} else if v, err := jsRuntime.ToValue(obj); err != nil {
return js.ReportError("could not convert '%s' to javascript object: %s", fileName, err)
} else {
return v
}
}
func jsFileExistsFunc(call otto.FunctionCall) otto.Value {
argv := call.ArgumentList
argc := len(argv)
if argc != 1 {
return js.ReportError("fileExists accepts one string argument")
} else if argv[0].IsString() == false {
return js.ReportError("fileExists accepts one string argument")
} else if fileName, err := fs.Expand(argv[0].String()); err != nil {
return js.ReportError("can't expand '%s': %v", fileName, err)
} else if fs.Exists(fileName) {
return otto.TrueValue()
}
return otto.FalseValue()
}

View file

@ -127,6 +127,10 @@ func New() (*Session, error) {
} }
} }
if bufSize := *s.Options.PcapBufSize; bufSize != -1 {
network.CAPTURE_DEFAULTS.Bufsize = bufSize
}
if s.Env, err = NewEnvironment(*s.Options.EnvFile); err != nil { if s.Env, err = NewEnvironment(*s.Options.EnvFile); err != nil {
return nil, err return nil, err
} }
@ -302,14 +306,15 @@ func (s *Session) Start() error {
s.startNetMon() s.startNetMon()
if *s.Options.Debug {
s.Events.Add("session.started", nil) s.Events.Add("session.started", nil)
}
// register js functions here to avoid cyclic dependency between // register js functions here to avoid cyclic dependency between
// js and session // js and session
plugin.Defines["env"] = jsEnvFunc plugin.Defines["env"] = jsEnvFunc
plugin.Defines["run"] = jsRunFunc plugin.Defines["run"] = jsRunFunc
plugin.Defines["fileExists"] = jsFileExistsFunc
plugin.Defines["loadJSON"] = jsLoadJSONFunc
plugin.Defines["saveJSON"] = jsSaveJSONFunc
plugin.Defines["onEvent"] = jsOnEventFunc plugin.Defines["onEvent"] = jsOnEventFunc
plugin.Defines["session"] = s plugin.Defines["session"] = s

View file

@ -155,6 +155,9 @@ 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 {
// notify any listener that the session is about to end
s.Events.Add("session.stopped", nil)
for _, mod := range s.Modules { for _, mod := range s.Modules {
if mod.Running() { if mod.Running() {
mod.Stop() mod.Stop()