misc: small fix or general refactoring i did not bother commenting

This commit is contained in:
evilsocket 2019-02-13 10:12:34 +01:00
parent bf3671465b
commit 4eead7eafa
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
58 changed files with 2052 additions and 2052 deletions

View file

@ -11,66 +11,66 @@ type AnyProxy struct {
} }
func NewAnyProxy(s *session.Session) *AnyProxy { func NewAnyProxy(s *session.Session) *AnyProxy {
p := &AnyProxy{ mod := &AnyProxy{
SessionModule: session.NewSessionModule("any.proxy", s), SessionModule: session.NewSessionModule("any.proxy", s),
} }
p.AddParam(session.NewStringParameter("any.proxy.iface", mod.AddParam(session.NewStringParameter("any.proxy.iface",
session.ParamIfaceName, session.ParamIfaceName,
"", "",
"Interface to redirect packets from.")) "Interface to redirect packets from."))
p.AddParam(session.NewStringParameter("any.proxy.protocol", mod.AddParam(session.NewStringParameter("any.proxy.protocol",
"TCP", "TCP",
"(TCP|UDP)", "(TCP|UDP)",
"Proxy protocol.")) "Proxy protocol."))
p.AddParam(session.NewIntParameter("any.proxy.src_port", mod.AddParam(session.NewIntParameter("any.proxy.src_port",
"80", "80",
"Remote port to redirect when the module is activated.")) "Remote port to redirect when the module is activated."))
p.AddParam(session.NewStringParameter("any.proxy.src_address", mod.AddParam(session.NewStringParameter("any.proxy.src_address",
"", "",
"", "",
"Leave empty to intercept any source address.")) "Leave empty to intercept any source address."))
p.AddParam(session.NewStringParameter("any.proxy.dst_address", mod.AddParam(session.NewStringParameter("any.proxy.dst_address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address where the proxy is listening.")) "Address where the proxy is listening."))
p.AddParam(session.NewIntParameter("any.proxy.dst_port", mod.AddParam(session.NewIntParameter("any.proxy.dst_port",
"8080", "8080",
"Port where the proxy is listening.")) "Port where the proxy is listening."))
p.AddHandler(session.NewModuleHandler("any.proxy on", "", mod.AddHandler(session.NewModuleHandler("any.proxy on", "",
"Start the custom proxy redirection.", "Start the custom proxy redirection.",
func(args []string) error { func(args []string) error {
return p.Start() return mod.Start()
})) }))
p.AddHandler(session.NewModuleHandler("any.proxy off", "", mod.AddHandler(session.NewModuleHandler("any.proxy off", "",
"Stop the custom proxy redirection.", "Stop the custom proxy redirection.",
func(args []string) error { func(args []string) error {
return p.Stop() return mod.Stop()
})) }))
return p return mod
} }
func (p *AnyProxy) Name() string { func (mod *AnyProxy) Name() string {
return "any.proxy" return "any.proxy"
} }
func (p *AnyProxy) Description() string { func (mod *AnyProxy) Description() string {
return "A firewall redirection to any custom proxy." return "A firewall redirection to any custom proxy."
} }
func (p *AnyProxy) Author() string { func (mod *AnyProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (p *AnyProxy) Configure() error { func (mod *AnyProxy) Configure() error {
var err error var err error
var srcPort int var srcPort int
var dstPort int var dstPort int
@ -79,62 +79,62 @@ func (p *AnyProxy) Configure() error {
var srcAddress string var srcAddress string
var dstAddress string var dstAddress string
if p.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, iface = p.StringParam("any.proxy.iface"); err != nil { } else if err, iface = mod.StringParam("any.proxy.iface"); err != nil {
return err return err
} else if err, protocol = p.StringParam("any.proxy.protocol"); err != nil { } else if err, protocol = mod.StringParam("any.proxy.protocol"); err != nil {
return err return err
} else if err, srcPort = p.IntParam("any.proxy.src_port"); err != nil { } else if err, srcPort = mod.IntParam("any.proxy.src_port"); err != nil {
return err return err
} else if err, dstPort = p.IntParam("any.proxy.dst_port"); err != nil { } else if err, dstPort = mod.IntParam("any.proxy.dst_port"); err != nil {
return err return err
} else if err, srcAddress = p.StringParam("any.proxy.src_address"); err != nil { } else if err, srcAddress = mod.StringParam("any.proxy.src_address"); err != nil {
return err return err
} else if err, dstAddress = p.StringParam("any.proxy.dst_address"); err != nil { } else if err, dstAddress = mod.StringParam("any.proxy.dst_address"); err != nil {
return err return err
} }
if !p.Session.Firewall.IsForwardingEnabled() { if !mod.Session.Firewall.IsForwardingEnabled() {
p.Info("Enabling forwarding.") mod.Info("Enabling forwarding.")
p.Session.Firewall.EnableForwarding(true) mod.Session.Firewall.EnableForwarding(true)
} }
p.Redirection = firewall.NewRedirection(iface, mod.Redirection = firewall.NewRedirection(iface,
protocol, protocol,
srcPort, srcPort,
dstAddress, dstAddress,
dstPort) dstPort)
if srcAddress != "" { if srcAddress != "" {
p.Redirection.SrcAddress = srcAddress mod.Redirection.SrcAddress = srcAddress
} }
if err := p.Session.Firewall.EnableRedirection(p.Redirection, true); err != nil { if err := mod.Session.Firewall.EnableRedirection(mod.Redirection, true); err != nil {
return err return err
} }
p.Info("Applied redirection %s", p.Redirection.String()) mod.Info("Applied redirection %s", mod.Redirection.String())
return nil return nil
} }
func (p *AnyProxy) Start() error { func (mod *AnyProxy) Start() error {
if err := p.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return p.SetRunning(true, func() {}) return mod.SetRunning(true, func() {})
} }
func (p *AnyProxy) Stop() error { func (mod *AnyProxy) Stop() error {
if p.Redirection != nil { if mod.Redirection != nil {
p.Info("Disabling redirection %s", p.Redirection.String()) mod.Info("Disabling redirection %s", mod.Redirection.String())
if err := p.Session.Firewall.EnableRedirection(p.Redirection, false); err != nil { if err := mod.Session.Firewall.EnableRedirection(mod.Redirection, false); err != nil {
return err return err
} }
p.Redirection = nil mod.Redirection = nil
} }
return p.SetRunning(false, func() {}) return mod.SetRunning(false, func() {})
} }

View file

@ -29,7 +29,7 @@ type RestAPI struct {
} }
func NewRestAPI(s *session.Session) *RestAPI { func NewRestAPI(s *session.Session) *RestAPI {
api := &RestAPI{ mod := &RestAPI{
SessionModule: session.NewSessionModule("api.rest", s), SessionModule: session.NewSessionModule("api.rest", s),
server: &http.Server{}, server: &http.Server{},
quit: make(chan bool), quit: make(chan bool),
@ -41,59 +41,59 @@ func NewRestAPI(s *session.Session) *RestAPI {
}, },
} }
api.AddParam(session.NewStringParameter("api.rest.address", mod.AddParam(session.NewStringParameter("api.rest.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address to bind the API REST server to.")) "Address to bind the API REST server to."))
api.AddParam(session.NewIntParameter("api.rest.port", mod.AddParam(session.NewIntParameter("api.rest.port",
"8081", "8081",
"Port to bind the API REST server to.")) "Port to bind the API REST server to."))
api.AddParam(session.NewStringParameter("api.rest.alloworigin", mod.AddParam(session.NewStringParameter("api.rest.alloworigin",
api.allowOrigin, mod.allowOrigin,
"", "",
"Value of the Access-Control-Allow-Origin header of the API server.")) "Value of the Access-Control-Allow-Origin header of the API server."))
api.AddParam(session.NewStringParameter("api.rest.username", mod.AddParam(session.NewStringParameter("api.rest.username",
"", "",
"", "",
"API authentication username.")) "API authentication username."))
api.AddParam(session.NewStringParameter("api.rest.password", mod.AddParam(session.NewStringParameter("api.rest.password",
"", "",
"", "",
"API authentication password.")) "API authentication password."))
api.AddParam(session.NewStringParameter("api.rest.certificate", mod.AddParam(session.NewStringParameter("api.rest.certificate",
"", "",
"", "",
"API TLS certificate.")) "API TLS certificate."))
tls.CertConfigToModule("api.rest", &api.SessionModule, tls.DefaultLegitConfig) tls.CertConfigToModule("api.rest", &mod.SessionModule, tls.DefaultLegitConfig)
api.AddParam(session.NewStringParameter("api.rest.key", mod.AddParam(session.NewStringParameter("api.rest.key",
"", "",
"", "",
"API TLS key")) "API TLS key"))
api.AddParam(session.NewBoolParameter("api.rest.websocket", mod.AddParam(session.NewBoolParameter("api.rest.websocket",
"false", "false",
"If true the /api/events route will be available as a websocket endpoint instead of HTTPS.")) "If true the /api/events route will be available as a websocket endpoint instead of HTTPS."))
api.AddHandler(session.NewModuleHandler("api.rest on", "", mod.AddHandler(session.NewModuleHandler("api.rest on", "",
"Start REST API server.", "Start REST API server.",
func(args []string) error { func(args []string) error {
return api.Start() return mod.Start()
})) }))
api.AddHandler(session.NewModuleHandler("api.rest off", "", mod.AddHandler(session.NewModuleHandler("api.rest off", "",
"Stop REST API server.", "Stop REST API server.",
func(args []string) error { func(args []string) error {
return api.Stop() return mod.Stop()
})) }))
return api return mod
} }
type JSSessionRequest struct { type JSSessionRequest struct {
@ -104,113 +104,113 @@ type JSSessionResponse struct {
Error string `json:"error"` Error string `json:"error"`
} }
func (api *RestAPI) Name() string { func (mod *RestAPI) Name() string {
return "api.rest" return "api.rest"
} }
func (api *RestAPI) Description() string { func (mod *RestAPI) Description() string {
return "Expose a RESTful API." return "Expose a RESTful API."
} }
func (api *RestAPI) Author() string { func (mod *RestAPI) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (api *RestAPI) isTLS() bool { func (mod *RestAPI) isTLS() bool {
return api.certFile != "" && api.keyFile != "" return mod.certFile != "" && mod.keyFile != ""
} }
func (api *RestAPI) Configure() error { func (mod *RestAPI) Configure() error {
var err error var err error
var ip string var ip string
var port int var port int
if api.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, ip = api.StringParam("api.rest.address"); err != nil { } else if err, ip = mod.StringParam("api.rest.address"); err != nil {
return err return err
} else if err, port = api.IntParam("api.rest.port"); err != nil { } else if err, port = mod.IntParam("api.rest.port"); err != nil {
return err return err
} else if err, api.allowOrigin = api.StringParam("api.rest.alloworigin"); err != nil { } else if err, mod.allowOrigin = mod.StringParam("api.rest.alloworigin"); err != nil {
return err return err
} else if err, api.certFile = api.StringParam("api.rest.certificate"); err != nil { } else if err, mod.certFile = mod.StringParam("api.rest.certificate"); err != nil {
return err return err
} else if api.certFile, err = fs.Expand(api.certFile); err != nil { } else if mod.certFile, err = fs.Expand(mod.certFile); err != nil {
return err return err
} else if err, api.keyFile = api.StringParam("api.rest.key"); err != nil { } else if err, mod.keyFile = mod.StringParam("api.rest.key"); err != nil {
return err return err
} else if api.keyFile, err = fs.Expand(api.keyFile); err != nil { } else if mod.keyFile, err = fs.Expand(mod.keyFile); err != nil {
return err return err
} else if err, api.username = api.StringParam("api.rest.username"); err != nil { } else if err, mod.username = mod.StringParam("api.rest.username"); err != nil {
return err return err
} else if err, api.password = api.StringParam("api.rest.password"); err != nil { } else if err, mod.password = mod.StringParam("api.rest.password"); err != nil {
return err return err
} else if err, api.useWebsocket = api.BoolParam("api.rest.websocket"); err != nil { } else if err, mod.useWebsocket = mod.BoolParam("api.rest.websocket"); err != nil {
return err return err
} }
if api.isTLS() { if mod.isTLS() {
if !fs.Exists(api.certFile) || !fs.Exists(api.keyFile) { if !fs.Exists(mod.certFile) || !fs.Exists(mod.keyFile) {
err, cfg := tls.CertConfigFromModule("api.rest", api.SessionModule) err, cfg := tls.CertConfigFromModule("api.rest", mod.SessionModule)
if err != nil { if err != nil {
return err return err
} }
api.Debug("%+v", cfg) mod.Debug("%+v", cfg)
api.Info("generating TLS key to %s", api.keyFile) mod.Info("generating TLS key to %s", mod.keyFile)
api.Info("generating TLS certificate to %s", api.certFile) mod.Info("generating TLS certificate to %s", mod.certFile)
if err := tls.Generate(cfg, api.certFile, api.keyFile); err != nil { if err := tls.Generate(cfg, mod.certFile, mod.keyFile); err != nil {
return err return err
} }
} else { } else {
api.Info("loading TLS key from %s", api.keyFile) mod.Info("loading TLS key from %s", mod.keyFile)
api.Info("loading TLS certificate from %s", api.certFile) mod.Info("loading TLS certificate from %s", mod.certFile)
} }
} }
api.server.Addr = fmt.Sprintf("%s:%d", ip, port) mod.server.Addr = fmt.Sprintf("%s:%d", ip, port)
router := mux.NewRouter() router := mux.NewRouter()
router.HandleFunc("/api/events", api.eventsRoute) router.HandleFunc("/api/events", mod.eventsRoute)
router.HandleFunc("/api/session", api.sessionRoute) router.HandleFunc("/api/session", mod.sessionRoute)
router.HandleFunc("/api/session/ble", api.sessionRoute) router.HandleFunc("/api/session/ble", mod.sessionRoute)
router.HandleFunc("/api/session/ble/{mac}", api.sessionRoute) router.HandleFunc("/api/session/ble/{mac}", mod.sessionRoute)
router.HandleFunc("/api/session/env", api.sessionRoute) router.HandleFunc("/api/session/env", mod.sessionRoute)
router.HandleFunc("/api/session/gateway", api.sessionRoute) router.HandleFunc("/api/session/gateway", mod.sessionRoute)
router.HandleFunc("/api/session/interface", api.sessionRoute) router.HandleFunc("/api/session/interface", mod.sessionRoute)
router.HandleFunc("/api/session/modules", api.sessionRoute) router.HandleFunc("/api/session/modules", mod.sessionRoute)
router.HandleFunc("/api/session/lan", api.sessionRoute) router.HandleFunc("/api/session/lan", mod.sessionRoute)
router.HandleFunc("/api/session/lan/{mac}", api.sessionRoute) router.HandleFunc("/api/session/lan/{mac}", mod.sessionRoute)
router.HandleFunc("/api/session/options", api.sessionRoute) router.HandleFunc("/api/session/options", mod.sessionRoute)
router.HandleFunc("/api/session/packets", api.sessionRoute) router.HandleFunc("/api/session/packets", mod.sessionRoute)
router.HandleFunc("/api/session/started-at", api.sessionRoute) router.HandleFunc("/api/session/started-at", mod.sessionRoute)
router.HandleFunc("/api/session/wifi", api.sessionRoute) router.HandleFunc("/api/session/wifi", mod.sessionRoute)
router.HandleFunc("/api/session/wifi/{mac}", api.sessionRoute) router.HandleFunc("/api/session/wifi/{mac}", mod.sessionRoute)
api.server.Handler = router mod.server.Handler = router
if api.username == "" || api.password == "" { if mod.username == "" || mod.password == "" {
api.Warning("api.rest.username and/or api.rest.password parameters are empty, authentication is disabled.") mod.Warning("api.rest.username and/or api.rest.password parameters are empty, authentication is disabled.")
} }
return nil return nil
} }
func (api *RestAPI) Start() error { func (mod *RestAPI) Start() error {
if err := api.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
api.SetRunning(true, func() { mod.SetRunning(true, func() {
var err error var err error
if api.isTLS() { if mod.isTLS() {
api.Info("api server starting on https://%s", api.server.Addr) mod.Info("api server starting on https://%s", mod.server.Addr)
err = api.server.ListenAndServeTLS(api.certFile, api.keyFile) err = mod.server.ListenAndServeTLS(mod.certFile, mod.keyFile)
} else { } else {
api.Info("api server starting on http://%s", api.server.Addr) mod.Info("api server starting on http://%s", mod.server.Addr)
err = api.server.ListenAndServe() err = mod.server.ListenAndServe()
} }
if err != nil && err != http.ErrServerClosed { if err != nil && err != http.ErrServerClosed {
@ -221,14 +221,14 @@ func (api *RestAPI) Start() error {
return nil return nil
} }
func (api *RestAPI) Stop() error { func (mod *RestAPI) Stop() error {
return api.SetRunning(false, func() { return mod.SetRunning(false, func() {
go func() { go func() {
api.quit <- true mod.quit <- true
}() }()
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel() defer cancel()
api.server.Shutdown(ctx) mod.server.Shutdown(ctx)
}) })
} }

View file

@ -21,116 +21,116 @@ type APIResponse struct {
Message string `json:"msg"` Message string `json:"msg"`
} }
func (api *RestAPI) setAuthFailed(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) setAuthFailed(w http.ResponseWriter, r *http.Request) {
api.Warning("Unauthorized authentication attempt from %s", r.RemoteAddr) mod.Warning("Unauthorized authentication attempt from %s", r.RemoteAddr)
w.Header().Set("WWW-Authenticate", `Basic realm="auth"`) w.Header().Set("WWW-Authenticate", `Basic realm="auth"`)
w.WriteHeader(401) w.WriteHeader(401)
w.Write([]byte("Unauthorized")) w.Write([]byte("Unauthorized"))
} }
func (api *RestAPI) toJSON(w http.ResponseWriter, o interface{}) { func (mod *RestAPI) toJSON(w http.ResponseWriter, o interface{}) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(o); err != nil { if err := json.NewEncoder(w).Encode(o); err != nil {
api.Error("error while encoding object to JSON: %v", err) mod.Error("error while encoding object to JSON: %v", err)
} }
} }
func (api *RestAPI) setSecurityHeaders(w http.ResponseWriter) { func (mod *RestAPI) setSecurityHeaders(w http.ResponseWriter) {
w.Header().Add("X-Frame-Options", "DENY") w.Header().Add("X-Frame-Options", "DENY")
w.Header().Add("X-Content-Type-Options", "nosniff") w.Header().Add("X-Content-Type-Options", "nosniff")
w.Header().Add("X-XSS-Protection", "1; mode=block") w.Header().Add("X-XSS-Protection", "1; mode=block")
w.Header().Add("Referrer-Policy", "same-origin") w.Header().Add("Referrer-Policy", "same-origin")
w.Header().Set("Access-Control-Allow-Origin", api.allowOrigin) w.Header().Set("Access-Control-Allow-Origin", mod.allowOrigin)
} }
func (api *RestAPI) checkAuth(r *http.Request) bool { func (mod *RestAPI) checkAuth(r *http.Request) bool {
if api.username != "" && api.password != "" { if mod.username != "" && mod.password != "" {
user, pass, _ := r.BasicAuth() user, pass, _ := r.BasicAuth()
// timing attack my ass // timing attack my ass
if subtle.ConstantTimeCompare([]byte(user), []byte(api.username)) != 1 { if subtle.ConstantTimeCompare([]byte(user), []byte(mod.username)) != 1 {
return false return false
} else if subtle.ConstantTimeCompare([]byte(pass), []byte(api.password)) != 1 { } else if subtle.ConstantTimeCompare([]byte(pass), []byte(mod.password)) != 1 {
return false return false
} }
} }
return true return true
} }
func (api *RestAPI) showSession(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showSession(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I) mod.toJSON(w, session.I)
} }
func (api *RestAPI) showBle(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showBle(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
mac := strings.ToLower(params["mac"]) mac := strings.ToLower(params["mac"])
if mac == "" { if mac == "" {
api.toJSON(w, session.I.BLE) mod.toJSON(w, session.I.BLE)
} else if dev, found := session.I.BLE.Get(mac); found { } else if dev, found := session.I.BLE.Get(mac); found {
api.toJSON(w, dev) mod.toJSON(w, dev)
} else { } else {
http.Error(w, "Not Found", 404) http.Error(w, "Not Found", 404)
} }
} }
func (api *RestAPI) showEnv(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showEnv(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I.Env) mod.toJSON(w, session.I.Env)
} }
func (api *RestAPI) showGateway(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showGateway(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I.Gateway) mod.toJSON(w, session.I.Gateway)
} }
func (api *RestAPI) showInterface(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showInterface(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I.Interface) mod.toJSON(w, session.I.Interface)
} }
func (api *RestAPI) showModules(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showModules(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I.Modules) mod.toJSON(w, session.I.Modules)
} }
func (api *RestAPI) showLan(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showLan(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
mac := strings.ToLower(params["mac"]) mac := strings.ToLower(params["mac"])
if mac == "" { if mac == "" {
api.toJSON(w, session.I.Lan) mod.toJSON(w, session.I.Lan)
} else if host, found := session.I.Lan.Get(mac); found { } else if host, found := session.I.Lan.Get(mac); found {
api.toJSON(w, host) mod.toJSON(w, host)
} else { } else {
http.Error(w, "Not Found", 404) http.Error(w, "Not Found", 404)
} }
} }
func (api *RestAPI) showOptions(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showOptions(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I.Options) mod.toJSON(w, session.I.Options)
} }
func (api *RestAPI) showPackets(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showPackets(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I.Queue) mod.toJSON(w, session.I.Queue)
} }
func (api *RestAPI) showStartedAt(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showStartedAt(w http.ResponseWriter, r *http.Request) {
api.toJSON(w, session.I.StartedAt) mod.toJSON(w, session.I.StartedAt)
} }
func (api *RestAPI) showWiFi(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showWiFi(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
mac := strings.ToLower(params["mac"]) mac := strings.ToLower(params["mac"])
if mac == "" { if mac == "" {
api.toJSON(w, session.I.WiFi) mod.toJSON(w, session.I.WiFi)
} else if station, found := session.I.WiFi.Get(mac); found { } else if station, found := session.I.WiFi.Get(mac); found {
api.toJSON(w, station) mod.toJSON(w, station)
} else if client, found := session.I.WiFi.GetClient(mac); found { } else if client, found := session.I.WiFi.GetClient(mac); found {
api.toJSON(w, client) mod.toJSON(w, client)
} else { } else {
http.Error(w, "Not Found", 404) http.Error(w, "Not Found", 404)
} }
} }
func (api *RestAPI) runSessionCommand(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) runSessionCommand(w http.ResponseWriter, r *http.Request) {
var err error var err error
var cmd CommandRequest var cmd CommandRequest
@ -141,15 +141,15 @@ func (api *RestAPI) runSessionCommand(w http.ResponseWriter, r *http.Request) {
} else if err = session.I.Run(cmd.Command); err != nil { } else if err = session.I.Run(cmd.Command); err != nil {
http.Error(w, err.Error(), 400) http.Error(w, err.Error(), 400)
} else { } else {
api.toJSON(w, APIResponse{Success: true}) mod.toJSON(w, APIResponse{Success: true})
} }
} }
func (api *RestAPI) showEvents(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) showEvents(w http.ResponseWriter, r *http.Request) {
var err error var err error
if api.useWebsocket { if mod.useWebsocket {
api.startStreamingEvents(w, r) mod.startStreamingEvents(w, r)
} else { } else {
events := session.I.Events.Sorted() events := session.I.Events.Sorted()
nevents := len(events) nevents := len(events)
@ -169,22 +169,22 @@ func (api *RestAPI) showEvents(w http.ResponseWriter, r *http.Request) {
} }
} }
api.toJSON(w, events[nevents-n:]) mod.toJSON(w, events[nevents-n:])
} }
} }
func (api *RestAPI) clearEvents(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) clearEvents(w http.ResponseWriter, r *http.Request) {
session.I.Events.Clear() session.I.Events.Clear()
} }
func (api *RestAPI) sessionRoute(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) sessionRoute(w http.ResponseWriter, r *http.Request) {
api.setSecurityHeaders(w) mod.setSecurityHeaders(w)
if !api.checkAuth(r) { if !mod.checkAuth(r) {
api.setAuthFailed(w, r) mod.setAuthFailed(w, r)
return return
} else if r.Method == "POST" { } else if r.Method == "POST" {
api.runSessionCommand(w, r) mod.runSessionCommand(w, r)
return return
} else if r.Method != "GET" { } else if r.Method != "GET" {
http.Error(w, "Bad Request", 400) http.Error(w, "Bad Request", 400)
@ -197,55 +197,55 @@ func (api *RestAPI) sessionRoute(w http.ResponseWriter, r *http.Request) {
path := r.URL.String() path := r.URL.String()
switch { switch {
case path == "/api/session": case path == "/api/session":
api.showSession(w, r) mod.showSession(w, r)
case path == "/api/session/env": case path == "/api/session/env":
api.showEnv(w, r) mod.showEnv(w, r)
case path == "/api/session/gateway": case path == "/api/session/gateway":
api.showGateway(w, r) mod.showGateway(w, r)
case path == "/api/session/interface": case path == "/api/session/interface":
api.showInterface(w, r) mod.showInterface(w, r)
case strings.HasPrefix(path, "/api/session/modules"): case strings.HasPrefix(path, "/api/session/modules"):
api.showModules(w, r) mod.showModules(w, r)
case strings.HasPrefix(path, "/api/session/lan"): case strings.HasPrefix(path, "/api/session/lan"):
api.showLan(w, r) mod.showLan(w, r)
case path == "/api/session/options": case path == "/api/session/options":
api.showOptions(w, r) mod.showOptions(w, r)
case path == "/api/session/packets": case path == "/api/session/packets":
api.showPackets(w, r) mod.showPackets(w, r)
case path == "/api/session/started-at": case path == "/api/session/started-at":
api.showStartedAt(w, r) mod.showStartedAt(w, r)
case strings.HasPrefix(path, "/api/session/ble"): case strings.HasPrefix(path, "/api/session/ble"):
api.showBle(w, r) mod.showBle(w, r)
case strings.HasPrefix(path, "/api/session/wifi"): case strings.HasPrefix(path, "/api/session/wifi"):
api.showWiFi(w, r) mod.showWiFi(w, r)
default: default:
http.Error(w, "Not Found", 404) http.Error(w, "Not Found", 404)
} }
} }
func (api *RestAPI) eventsRoute(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) eventsRoute(w http.ResponseWriter, r *http.Request) {
api.setSecurityHeaders(w) mod.setSecurityHeaders(w)
if !api.checkAuth(r) { if !mod.checkAuth(r) {
api.setAuthFailed(w, r) mod.setAuthFailed(w, r)
return return
} }
if r.Method == "GET" { if r.Method == "GET" {
api.showEvents(w, r) mod.showEvents(w, r)
} else if r.Method == "DELETE" { } else if r.Method == "DELETE" {
api.clearEvents(w, r) mod.clearEvents(w, r)
} else { } else {
http.Error(w, "Bad Request", 400) http.Error(w, "Bad Request", 400)
} }

View file

@ -20,17 +20,17 @@ const (
pingPeriod = (pongWait * 9) / 10 pingPeriod = (pongWait * 9) / 10
) )
func (api *RestAPI) streamEvent(ws *websocket.Conn, event session.Event) error { func (mod *RestAPI) streamEvent(ws *websocket.Conn, event session.Event) error {
msg, err := json.Marshal(event) msg, err := json.Marshal(event)
if err != nil { if err != nil {
api.Error("Error while creating websocket message: %s", err) mod.Error("Error while creating websocket message: %s", err)
return err return err
} }
ws.SetWriteDeadline(time.Now().Add(writeWait)) ws.SetWriteDeadline(time.Now().Add(writeWait))
if err := ws.WriteMessage(websocket.TextMessage, msg); err != nil { if err := ws.WriteMessage(websocket.TextMessage, msg); err != nil {
if !strings.Contains(err.Error(), "closed connection") { if !strings.Contains(err.Error(), "closed connection") {
api.Error("Error while writing websocket message: %s", err) mod.Error("Error while writing websocket message: %s", err)
return err return err
} }
} }
@ -38,25 +38,25 @@ func (api *RestAPI) streamEvent(ws *websocket.Conn, event session.Event) error {
return nil return nil
} }
func (api *RestAPI) sendPing(ws *websocket.Conn) error { func (mod *RestAPI) sendPing(ws *websocket.Conn) error {
ws.SetWriteDeadline(time.Now().Add(writeWait)) ws.SetWriteDeadline(time.Now().Add(writeWait))
if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil { if err := ws.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
api.Error("Error while writing websocket ping message: %s", err) mod.Error("Error while writing websocket ping message: %s", err)
return err return err
} }
return nil return nil
} }
func (api *RestAPI) streamWriter(ws *websocket.Conn, w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) streamWriter(ws *websocket.Conn, w http.ResponseWriter, r *http.Request) {
defer ws.Close() defer ws.Close()
// first we stream what we already have // first we stream what we already have
events := session.I.Events.Sorted() events := session.I.Events.Sorted()
n := len(events) n := len(events)
if n > 0 { if n > 0 {
api.Debug("Sending %d events.", n) mod.Debug("Sending %d events.", n)
for _, event := range events { for _, event := range events {
if err := api.streamEvent(ws, event); err != nil { if err := mod.streamEvent(ws, event); err != nil {
return return
} }
} }
@ -64,7 +64,7 @@ func (api *RestAPI) streamWriter(ws *websocket.Conn, w http.ResponseWriter, r *h
session.I.Events.Clear() session.I.Events.Clear()
api.Debug("Listening for events and streaming to ws endpoint ...") mod.Debug("Listening for events and streaming to ws endpoint ...")
pingTicker := time.NewTicker(pingPeriod) pingTicker := time.NewTicker(pingPeriod)
listener := session.I.Events.Listen() listener := session.I.Events.Listen()
@ -73,21 +73,21 @@ func (api *RestAPI) streamWriter(ws *websocket.Conn, w http.ResponseWriter, r *h
for { for {
select { select {
case <-pingTicker.C: case <-pingTicker.C:
if err := api.sendPing(ws); err != nil { if err := mod.sendPing(ws); err != nil {
return return
} }
case event := <-listener: case event := <-listener:
if err := api.streamEvent(ws, event); err != nil { if err := mod.streamEvent(ws, event); err != nil {
return return
} }
case <-api.quit: case <-mod.quit:
api.Info("Stopping websocket events streamer ...") mod.Info("Stopping websocket events streamer ...")
return return
} }
} }
} }
func (api *RestAPI) streamReader(ws *websocket.Conn) { func (mod *RestAPI) streamReader(ws *websocket.Conn) {
defer ws.Close() defer ws.Close()
ws.SetReadLimit(512) ws.SetReadLimit(512)
ws.SetReadDeadline(time.Now().Add(pongWait)) ws.SetReadDeadline(time.Now().Add(pongWait))
@ -95,23 +95,23 @@ func (api *RestAPI) streamReader(ws *websocket.Conn) {
for { for {
_, _, err := ws.ReadMessage() _, _, err := ws.ReadMessage()
if err != nil { if err != nil {
api.Debug("Closing websocket reader.") mod.Debug("Closing websocket reader.")
break break
} }
} }
} }
func (api *RestAPI) startStreamingEvents(w http.ResponseWriter, r *http.Request) { func (mod *RestAPI) startStreamingEvents(w http.ResponseWriter, r *http.Request) {
ws, err := api.upgrader.Upgrade(w, r, nil) ws, err := mod.upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
if _, ok := err.(websocket.HandshakeError); !ok { if _, ok := err.(websocket.HandshakeError); !ok {
api.Error("Error while updating api.rest connection to websocket: %s", err) mod.Error("Error while updating api.rest connection to websocket: %s", err)
} }
return return
} }
api.Debug("Websocket streaming started for %s", r.RemoteAddr) mod.Debug("Websocket streaming started for %s", r.RemoteAddr)
go api.streamWriter(ws, w, r) go mod.streamWriter(ws, w, r)
api.streamReader(ws) mod.streamReader(ws)
} }

View file

@ -26,7 +26,7 @@ type ArpSpoofer struct {
} }
func NewArpSpoofer(s *session.Session) *ArpSpoofer { func NewArpSpoofer(s *session.Session) *ArpSpoofer {
p := &ArpSpoofer{ mod := &ArpSpoofer{
SessionModule: session.NewSessionModule("arp.spoof", s), SessionModule: session.NewSessionModule("arp.spoof", s),
addresses: make([]net.IP, 0), addresses: make([]net.IP, 0),
macs: make([]net.HardwareAddr, 0), macs: make([]net.HardwareAddr, 0),
@ -38,123 +38,123 @@ func NewArpSpoofer(s *session.Session) *ArpSpoofer {
waitGroup: &sync.WaitGroup{}, waitGroup: &sync.WaitGroup{},
} }
p.AddParam(session.NewStringParameter("arp.spoof.targets", session.ParamSubnet, "", "Comma separated list of IP addresses, MAC addresses or aliases to spoof, also supports nmap style IP ranges.")) mod.AddParam(session.NewStringParameter("arp.spoof.targets", session.ParamSubnet, "", "Comma separated list of IP addresses, MAC addresses or aliases to spoof, also supports nmap style IP ranges."))
p.AddParam(session.NewStringParameter("arp.spoof.whitelist", "", "", "Comma separated list of IP addresses, MAC addresses or aliases to skip while spoofing.")) mod.AddParam(session.NewStringParameter("arp.spoof.whitelist", "", "", "Comma separated list of IP addresses, MAC addresses or aliases to skip while spoofing."))
p.AddParam(session.NewBoolParameter("arp.spoof.internal", mod.AddParam(session.NewBoolParameter("arp.spoof.internal",
"false", "false",
"If true, local connections among computers of the network will be spoofed, otherwise only connections going to and coming from the external network.")) "If true, local connections among computers of the network will be spoofed, otherwise only connections going to and coming from the external network."))
p.AddParam(session.NewBoolParameter("arp.spoof.fullduplex", mod.AddParam(session.NewBoolParameter("arp.spoof.fullduplex",
"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)."))
p.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 {
return p.Start() return mod.Start()
})) }))
p.AddHandler(session.NewModuleHandler("arp.ban on", "", mod.AddHandler(session.NewModuleHandler("arp.ban on", "",
"Start ARP spoofer in ban mode, meaning the target(s) connectivity will not work.", "Start ARP spoofer in ban mode, meaning the target(s) connectivity will not work.",
func(args []string) error { func(args []string) error {
p.ban = true mod.ban = true
return p.Start() return mod.Start()
})) }))
p.AddHandler(session.NewModuleHandler("arp.spoof off", "", mod.AddHandler(session.NewModuleHandler("arp.spoof off", "",
"Stop ARP spoofer.", "Stop ARP spoofer.",
func(args []string) error { func(args []string) error {
return p.Stop() return mod.Stop()
})) }))
p.AddHandler(session.NewModuleHandler("arp.ban off", "", mod.AddHandler(session.NewModuleHandler("arp.ban off", "",
"Stop ARP spoofer.", "Stop ARP spoofer.",
func(args []string) error { func(args []string) error {
return p.Stop() return mod.Stop()
})) }))
return p return mod
} }
func (p ArpSpoofer) Name() string { func (mod ArpSpoofer) Name() string {
return "arp.spoof" return "arp.spoof"
} }
func (p ArpSpoofer) Description() string { func (mod ArpSpoofer) Description() string {
return "Keep spoofing selected hosts on the network." return "Keep spoofing selected hosts on the network."
} }
func (p ArpSpoofer) Author() string { func (mod ArpSpoofer) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (p *ArpSpoofer) Configure() error { func (mod *ArpSpoofer) Configure() error {
var err error var err error
var targets string var targets string
var whitelist string var whitelist string
if err, p.fullDuplex = p.BoolParam("arp.spoof.fullduplex"); err != nil { if err, mod.fullDuplex = mod.BoolParam("arp.spoof.fullduplex"); err != nil {
return err return err
} else if err, p.internal = p.BoolParam("arp.spoof.internal"); err != nil { } else if err, mod.internal = mod.BoolParam("arp.spoof.internal"); err != nil {
return err return err
} else if err, targets = p.StringParam("arp.spoof.targets"); err != nil { } else if err, targets = mod.StringParam("arp.spoof.targets"); err != nil {
return err return err
} else if err, whitelist = p.StringParam("arp.spoof.whitelist"); err != nil { } else if err, whitelist = mod.StringParam("arp.spoof.whitelist"); err != nil {
return err return err
} else if p.addresses, p.macs, err = network.ParseTargets(targets, p.Session.Lan.Aliases()); err != nil { } else if mod.addresses, mod.macs, err = network.ParseTargets(targets, mod.Session.Lan.Aliases()); err != nil {
return err return err
} else if p.wAddresses, p.wMacs, err = network.ParseTargets(whitelist, p.Session.Lan.Aliases()); err != nil { } else if mod.wAddresses, mod.wMacs, err = network.ParseTargets(whitelist, mod.Session.Lan.Aliases()); err != nil {
return err return err
} }
p.Debug(" addresses=%v macs=%v whitelisted-addresses=%v whitelisted-macs=%v", p.addresses, p.macs, p.wAddresses, p.wMacs) mod.Debug(" addresses=%v macs=%v whitelisted-addresses=%v whitelisted-macs=%v", mod.addresses, mod.macs, mod.wAddresses, mod.wMacs)
if p.ban { if mod.ban {
p.Warning("running in ban mode, forwarding not enabled!") mod.Warning("running in ban mode, forwarding not enabled!")
p.Session.Firewall.EnableForwarding(false) mod.Session.Firewall.EnableForwarding(false)
} else if !p.Session.Firewall.IsForwardingEnabled() { } else if !mod.Session.Firewall.IsForwardingEnabled() {
p.Info("enabling forwarding") mod.Info("enabling forwarding")
p.Session.Firewall.EnableForwarding(true) mod.Session.Firewall.EnableForwarding(true)
} }
return nil return nil
} }
func (p *ArpSpoofer) Start() error { func (mod *ArpSpoofer) Start() error {
if err := p.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return p.SetRunning(true, func() { return mod.SetRunning(true, func() {
neighbours := []net.IP{} neighbours := []net.IP{}
nTargets := len(p.addresses) + len(p.macs) nTargets := len(mod.addresses) + len(mod.macs)
if p.internal { if mod.internal {
list, _ := iprange.ParseList(p.Session.Interface.CIDR()) list, _ := iprange.ParseList(mod.Session.Interface.CIDR())
neighbours = list.Expand() neighbours = list.Expand()
nNeigh := len(neighbours) - 2 nNeigh := len(neighbours) - 2
p.Warning("arp spoofer started targeting %d possible network neighbours of %d targets.", nNeigh, nTargets) mod.Warning("arp spoofer started targeting %d possible network neighbours of %d targets.", nNeigh, nTargets)
} else { } else {
p.Info("arp spoofer started, probing %d targets.", nTargets) mod.Info("arp spoofer started, probing %d targets.", nTargets)
} }
if p.fullDuplex { if mod.fullDuplex {
p.Warning("full duplex spoofing enabled, if the router has ARP spoofing mechanisms, the attack will fail.") mod.Warning("full duplex spoofing enabled, if the router has ARP spoofing mechanisms, the attack will fail.")
} }
p.waitGroup.Add(1) mod.waitGroup.Add(1)
defer p.waitGroup.Done() defer mod.waitGroup.Done()
gwIP := p.Session.Gateway.IP gwIP := mod.Session.Gateway.IP
myMAC := p.Session.Interface.HW myMAC := mod.Session.Interface.HW
for p.Running() { for mod.Running() {
p.arpSpoofTargets(gwIP, myMAC, true, false) mod.arpSpoofTargets(gwIP, myMAC, true, false)
for _, address := range neighbours { for _, address := range neighbours {
if !p.Session.Skip(address) { if !mod.Session.Skip(address) {
p.arpSpoofTargets(address, myMAC, true, false) mod.arpSpoofTargets(address, myMAC, true, false)
} }
} }
@ -163,18 +163,18 @@ func (p *ArpSpoofer) Start() error {
}) })
} }
func (p *ArpSpoofer) unSpoof() error { func (mod *ArpSpoofer) unSpoof() error {
nTargets := len(p.addresses) + len(p.macs) nTargets := len(mod.addresses) + len(mod.macs)
p.Info("restoring ARP cache of %d targets.", nTargets) mod.Info("restoring ARP cache of %d targets.", nTargets)
p.arpSpoofTargets(p.Session.Gateway.IP, p.Session.Gateway.HW, false, false) mod.arpSpoofTargets(mod.Session.Gateway.IP, mod.Session.Gateway.HW, false, false)
if p.internal { if mod.internal {
list, _ := iprange.ParseList(p.Session.Interface.CIDR()) list, _ := iprange.ParseList(mod.Session.Interface.CIDR())
neighbours := list.Expand() neighbours := list.Expand()
for _, address := range neighbours { for _, address := range neighbours {
if !p.Session.Skip(address) { if !mod.Session.Skip(address) {
if realMAC, err := p.Session.FindMAC(address, false); err == nil { if realMAC, err := mod.Session.FindMAC(address, false); err == nil {
p.arpSpoofTargets(address, realMAC, false, false) mod.arpSpoofTargets(address, realMAC, false, false)
} }
} }
} }
@ -183,23 +183,23 @@ func (p *ArpSpoofer) unSpoof() error {
return nil return nil
} }
func (p *ArpSpoofer) Stop() error { func (mod *ArpSpoofer) Stop() error {
return p.SetRunning(false, func() { return mod.SetRunning(false, func() {
p.Info("waiting for ARP spoofer to stop ...") mod.Info("waiting for ARP spoofer to stop ...")
p.unSpoof() mod.unSpoof()
p.ban = false mod.ban = false
p.waitGroup.Wait() mod.waitGroup.Wait()
}) })
} }
func (p *ArpSpoofer) isWhitelisted(ip string, mac net.HardwareAddr) bool { func (mod *ArpSpoofer) isWhitelisted(ip string, mac net.HardwareAddr) bool {
for _, addr := range p.wAddresses { for _, addr := range mod.wAddresses {
if ip == addr.String() { if ip == addr.String() {
return true return true
} }
} }
for _, hw := range p.wMacs { for _, hw := range mod.wMacs {
if bytes.Equal(hw, mac) { if bytes.Equal(hw, mac) {
return true return true
} }
@ -208,28 +208,28 @@ func (p *ArpSpoofer) isWhitelisted(ip string, mac net.HardwareAddr) bool {
return false return false
} }
func (p *ArpSpoofer) getTargets(probe bool) map[string]net.HardwareAddr { func (mod *ArpSpoofer) getTargets(probe bool) map[string]net.HardwareAddr {
targets := make(map[string]net.HardwareAddr) targets := make(map[string]net.HardwareAddr)
// add targets specified by IP address // add targets specified by IP address
for _, ip := range p.addresses { for _, ip := range mod.addresses {
if p.Session.Skip(ip) { if mod.Session.Skip(ip) {
p.Debug("skipping IP %s from arp spoofing.", ip) mod.Debug("skipping IP %s from arp spoofing.", ip)
continue continue
} }
// do we have this ip mac address? // do we have this ip mac address?
if hw, err := p.Session.FindMAC(ip, probe); err != nil { if hw, err := mod.Session.FindMAC(ip, probe); err != nil {
p.Debug("could not find hardware address for %s", ip.String()) mod.Debug("could not find hardware address for %s", ip.String())
} else { } else {
targets[ip.String()] = hw targets[ip.String()] = hw
} }
} }
// add targets specified by MAC address // add targets specified by MAC address
for _, hw := range p.macs { for _, hw := range mod.macs {
if ip, err := network.ArpInverseLookup(p.Session.Interface.Name(), hw.String(), false); err != nil { if ip, err := network.ArpInverseLookup(mod.Session.Interface.Name(), hw.String(), false); err != nil {
p.Warning("could not find IP address for %s", hw.String()) mod.Warning("could not find IP address for %s", hw.String())
} else if p.Session.Skip(net.ParseIP(ip)) { } else if mod.Session.Skip(net.ParseIP(ip)) {
p.Debug("skipping address %s from arp spoofing.", ip) mod.Debug("skipping address %s from arp spoofing.", ip)
} else { } else {
targets[ip] = hw targets[ip] = hw
} }
@ -238,13 +238,13 @@ func (p *ArpSpoofer) getTargets(probe bool) map[string]net.HardwareAddr {
return targets return targets
} }
func (p *ArpSpoofer) arpSpoofTargets(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) { func (mod *ArpSpoofer) arpSpoofTargets(saddr net.IP, smac net.HardwareAddr, check_running bool, probe bool) {
p.waitGroup.Add(1) mod.waitGroup.Add(1)
defer p.waitGroup.Done() defer mod.waitGroup.Done()
gwIP := p.Session.Gateway.IP gwIP := mod.Session.Gateway.IP
gwHW := p.Session.Gateway.HW gwHW := mod.Session.Gateway.HW
ourHW := p.Session.Interface.HW ourHW := mod.Session.Interface.HW
isGW := false isGW := false
isSpoofing := false isSpoofing := false
@ -257,11 +257,11 @@ func (p *ArpSpoofer) arpSpoofTargets(saddr net.IP, smac net.HardwareAddr, check_
} }
} }
for ip, mac := range p.getTargets(probe) { for ip, mac := range mod.getTargets(probe) {
if check_running && !p.Running() { if check_running && !mod.Running() {
return return
} else if p.isWhitelisted(ip, mac) { } else if mod.isWhitelisted(ip, mac) {
p.Debug("%s (%s) is whitelisted, skipping from spoofing loop.", ip, mac) mod.Debug("%s (%s) is whitelisted, skipping from spoofing loop.", ip, mac)
continue continue
} else if saddr.String() == ip { } else if saddr.String() == ip {
continue continue
@ -269,34 +269,34 @@ func (p *ArpSpoofer) arpSpoofTargets(saddr net.IP, smac net.HardwareAddr, check_
rawIP := net.ParseIP(ip) rawIP := net.ParseIP(ip)
if err, pkt := packets.NewARPReply(saddr, smac, rawIP, mac); err != nil { if err, pkt := packets.NewARPReply(saddr, smac, rawIP, mac); err != nil {
p.Error("error while creating ARP spoof packet for %s: %s", ip, err) mod.Error("error while creating ARP spoof packet for %s: %s", ip, err)
} else { } else {
p.Debug("sending %d bytes of ARP packet to %s:%s.", len(pkt), ip, mac.String()) mod.Debug("sending %d bytes of ARP packet to %s:%s.", len(pkt), ip, mac.String())
p.Session.Queue.Send(pkt) mod.Session.Queue.Send(pkt)
} }
if p.fullDuplex && isGW { if mod.fullDuplex && isGW {
err := error(nil) err := error(nil)
gwPacket := []byte(nil) gwPacket := []byte(nil)
if isSpoofing { if isSpoofing {
p.Debug("telling the gw we are %s", ip) mod.Debug("telling the gw we are %s", ip)
// we told the target we're te gateway, not let's tell the // we told the target we're te gateway, not let's tell the
// gateway that we are the target // gateway that we are the target
if err, gwPacket = packets.NewARPReply(rawIP, ourHW, gwIP, gwHW); err != nil { if err, gwPacket = packets.NewARPReply(rawIP, ourHW, gwIP, gwHW); err != nil {
p.Error("error while creating ARP spoof packet: %s", err) mod.Error("error while creating ARP spoof packet: %s", err)
} }
} else { } else {
p.Debug("telling the gw %s is %s", ip, mac) mod.Debug("telling the gw %s is %s", ip, mac)
// send the gateway the original MAC of the target // send the gateway the original MAC of the target
if err, gwPacket = packets.NewARPReply(rawIP, mac, gwIP, gwHW); err != nil { if err, gwPacket = packets.NewARPReply(rawIP, mac, gwIP, gwHW); err != nil {
p.Error("error while creating ARP spoof packet: %s", err) mod.Error("error while creating ARP spoof packet: %s", err)
} }
} }
if gwPacket != nil { if gwPacket != nil {
if err = p.Session.Queue.Send(gwPacket); err != nil { if err = mod.Session.Queue.Send(gwPacket); err != nil {
p.Error("error while sending packet: %v", err) mod.Error("error while sending packet: %v", err)
} }
} }
} }

View file

@ -29,7 +29,7 @@ type BLERecon struct {
} }
func NewBLERecon(s *session.Session) *BLERecon { func NewBLERecon(s *session.Session) *BLERecon {
d := &BLERecon{ mod := &BLERecon{
SessionModule: session.NewSessionModule("ble.recon", s), SessionModule: session.NewSessionModule("ble.recon", s),
gattDevice: nil, gattDevice: nil,
quit: make(chan bool), quit: make(chan bool),
@ -39,38 +39,38 @@ func NewBLERecon(s *session.Session) *BLERecon {
connected: false, connected: false,
} }
d.AddHandler(session.NewModuleHandler("ble.recon on", "", mod.AddHandler(session.NewModuleHandler("ble.recon on", "",
"Start Bluetooth Low Energy devices discovery.", "Start Bluetooth Low Energy devices discovery.",
func(args []string) error { func(args []string) error {
return d.Start() return mod.Start()
})) }))
d.AddHandler(session.NewModuleHandler("ble.recon off", "", mod.AddHandler(session.NewModuleHandler("ble.recon off", "",
"Stop Bluetooth Low Energy devices discovery.", "Stop Bluetooth Low Energy devices discovery.",
func(args []string) error { func(args []string) error {
return d.Stop() return mod.Stop()
})) }))
d.AddHandler(session.NewModuleHandler("ble.show", "", mod.AddHandler(session.NewModuleHandler("ble.show", "",
"Show discovered Bluetooth Low Energy devices.", "Show discovered Bluetooth Low Energy devices.",
func(args []string) error { func(args []string) error {
return d.Show() return mod.Show()
})) }))
d.AddHandler(session.NewModuleHandler("ble.enum MAC", "ble.enum "+network.BLEMacValidator, mod.AddHandler(session.NewModuleHandler("ble.enum MAC", "ble.enum "+network.BLEMacValidator,
"Enumerate services and characteristics for the given BLE device.", "Enumerate services and characteristics for the given BLE device.",
func(args []string) error { func(args []string) error {
if d.isEnumerating() { if mod.isEnumerating() {
return fmt.Errorf("An enumeration for %s is already running, please wait.", d.currDevice.Device.ID()) return fmt.Errorf("An enumeration for %s is already running, please wait.", mod.currDevice.Device.ID())
} }
d.writeData = nil mod.writeData = nil
d.writeUUID = nil mod.writeUUID = nil
return d.enumAllTheThings(network.NormalizeMac(args[0])) return mod.enumAllTheThings(network.NormalizeMac(args[0]))
})) }))
d.AddHandler(session.NewModuleHandler("ble.write MAC UUID HEX_DATA", "ble.write "+network.BLEMacValidator+" ([a-fA-F0-9]+) ([a-fA-F0-9]+)", mod.AddHandler(session.NewModuleHandler("ble.write MAC UUID HEX_DATA", "ble.write "+network.BLEMacValidator+" ([a-fA-F0-9]+) ([a-fA-F0-9]+)",
"Write the HEX_DATA buffer to the BLE device with the specified MAC address, to the characteristics with the given UUID.", "Write the HEX_DATA buffer to the BLE device with the specified MAC address, to the characteristics with the given UUID.",
func(args []string) error { func(args []string) error {
mac := network.NormalizeMac(args[0]) mac := network.NormalizeMac(args[0])
@ -83,84 +83,84 @@ func NewBLERecon(s *session.Session) *BLERecon {
return fmt.Errorf("Error parsing %s: %s", args[2], err) return fmt.Errorf("Error parsing %s: %s", args[2], err)
} }
return d.writeBuffer(mac, uuid, data) return mod.writeBuffer(mac, uuid, data)
})) }))
return d return mod
} }
func (d BLERecon) Name() string { func (mod BLERecon) Name() string {
return "ble.recon" return "ble.recon"
} }
func (d BLERecon) Description() string { func (mod BLERecon) Description() string {
return "Bluetooth Low Energy devices discovery." return "Bluetooth Low Energy devices discovery."
} }
func (d BLERecon) Author() string { func (mod BLERecon) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (d *BLERecon) isEnumerating() bool { func (mod *BLERecon) isEnumerating() bool {
return d.currDevice != nil return mod.currDevice != nil
} }
func (d *BLERecon) Configure() (err error) { func (mod *BLERecon) Configure() (err error) {
if d.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if d.gattDevice == nil { } else if mod.gattDevice == nil {
d.Info("Initializing BLE device ...") mod.Info("Initializing BLE device ...")
// hey Paypal GATT library, could you please just STFU?! // hey Paypal GATT library, could you please just STFU?!
golog.SetOutput(ioutil.Discard) golog.SetOutput(ioutil.Discard)
if d.gattDevice, err = gatt.NewDevice(defaultBLEClientOptions...); err != nil { if mod.gattDevice, err = gatt.NewDevice(defaultBLEClientOptions...); err != nil {
return err return err
} }
d.gattDevice.Handle( mod.gattDevice.Handle(
gatt.PeripheralDiscovered(d.onPeriphDiscovered), gatt.PeripheralDiscovered(mod.onPeriphDiscovered),
gatt.PeripheralConnected(d.onPeriphConnected), gatt.PeripheralConnected(mod.onPeriphConnected),
gatt.PeripheralDisconnected(d.onPeriphDisconnected), gatt.PeripheralDisconnected(mod.onPeriphDisconnected),
) )
d.gattDevice.Init(d.onStateChanged) mod.gattDevice.Init(mod.onStateChanged)
} }
return nil return nil
} }
func (d *BLERecon) Start() error { func (mod *BLERecon) Start() error {
if err := d.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return d.SetRunning(true, func() { return mod.SetRunning(true, func() {
go d.pruner() go mod.pruner()
<-d.quit <-mod.quit
d.Info("Stopping BLE scan ...") mod.Info("Stopping BLE scan ...")
d.gattDevice.StopScanning() mod.gattDevice.StopScanning()
d.done <- true mod.done <- true
}) })
} }
func (d *BLERecon) Stop() error { func (mod *BLERecon) Stop() error {
return d.SetRunning(false, func() { return mod.SetRunning(false, func() {
d.quit <- true mod.quit <- true
<-d.done <-mod.done
}) })
} }
func (d *BLERecon) pruner() { func (mod *BLERecon) pruner() {
d.Debug("Started BLE devices pruner ...") mod.Debug("Started BLE devices pruner ...")
for d.Running() { for mod.Running() {
for _, dev := range d.Session.BLE.Devices() { for _, dev := range mod.Session.BLE.Devices() {
if time.Since(dev.LastSeen) > blePresentInterval { if time.Since(dev.LastSeen) > blePresentInterval {
d.Session.BLE.Remove(dev.Device.ID()) mod.Session.BLE.Remove(dev.Device.ID())
} }
} }
@ -168,41 +168,41 @@ func (d *BLERecon) pruner() {
} }
} }
func (d *BLERecon) setCurrentDevice(dev *network.BLEDevice) { func (mod *BLERecon) setCurrentDevice(dev *network.BLEDevice) {
d.connected = false mod.connected = false
d.currDevice = dev mod.currDevice = dev
} }
func (d *BLERecon) writeBuffer(mac string, uuid gatt.UUID, data []byte) error { func (mod *BLERecon) writeBuffer(mac string, uuid gatt.UUID, data []byte) error {
d.writeUUID = &uuid mod.writeUUID = &uuid
d.writeData = data mod.writeData = data
return d.enumAllTheThings(mac) return mod.enumAllTheThings(mac)
} }
func (d *BLERecon) enumAllTheThings(mac string) error { func (mod *BLERecon) enumAllTheThings(mac string) error {
dev, found := d.Session.BLE.Get(mac) dev, found := mod.Session.BLE.Get(mac)
if !found || dev == nil { if !found || dev == nil {
return fmt.Errorf("BLE device with address %s not found.", mac) return fmt.Errorf("BLE device with address %s not found.", mac)
} else if d.Running() { } else if mod.Running() {
d.gattDevice.StopScanning() mod.gattDevice.StopScanning()
} }
d.setCurrentDevice(dev) mod.setCurrentDevice(dev)
if err := d.Configure(); err != nil && err != session.ErrAlreadyStarted { if err := mod.Configure(); err != nil && err != session.ErrAlreadyStarted {
return err return err
} }
d.Info("Connecting to %s ...", mac) mod.Info("Connecting to %s ...", mac)
go func() { go func() {
time.Sleep(d.connTimeout) time.Sleep(mod.connTimeout)
if d.isEnumerating() && !d.connected { if mod.isEnumerating() && !mod.connected {
d.Session.Events.Add("ble.connection.timeout", d.currDevice) mod.Session.Events.Add("ble.connection.timeout", mod.currDevice)
d.onPeriphDisconnected(nil, nil) mod.onPeriphDisconnected(nil, nil)
} }
}() }()
d.gattDevice.Connect(dev.Device) mod.gattDevice.Connect(dev.Device)
return nil return nil
} }

View file

@ -7,65 +7,65 @@ import (
"github.com/bettercap/gatt" "github.com/bettercap/gatt"
) )
func (d *BLERecon) onStateChanged(dev gatt.Device, s gatt.State) { func (mod *BLERecon) onStateChanged(dev gatt.Device, s gatt.State) {
d.Info("BLE state changed to %v", s) mod.Info("BLE state changed to %v", s)
switch s { switch s {
case gatt.StatePoweredOn: case gatt.StatePoweredOn:
if d.currDevice == nil { if mod.currDevice == nil {
d.Info("Starting BLE discovery ...") mod.Info("Starting BLE discovery ...")
dev.Scan([]gatt.UUID{}, true) dev.Scan([]gatt.UUID{}, true)
} }
case gatt.StatePoweredOff: case gatt.StatePoweredOff:
d.gattDevice = nil mod.gattDevice = nil
default: default:
d.Warning("Unexpected BLE state: %v", s) mod.Warning("Unexpected BLE state: %v", s)
} }
} }
func (d *BLERecon) onPeriphDiscovered(p gatt.Peripheral, a *gatt.Advertisement, rssi int) { func (mod *BLERecon) onPeriphDiscovered(p gatt.Peripheral, a *gatt.Advertisement, rssi int) {
d.Session.BLE.AddIfNew(p.ID(), p, a, rssi) mod.Session.BLE.AddIfNew(p.ID(), p, a, rssi)
} }
func (d *BLERecon) onPeriphDisconnected(p gatt.Peripheral, err error) { func (mod *BLERecon) onPeriphDisconnected(p gatt.Peripheral, err error) {
if d.Running() { if mod.Running() {
// restore scanning // restore scanning
d.Info("Device disconnected, restoring BLE discovery.") mod.Info("Device disconnected, restoring BLE discovery.")
d.setCurrentDevice(nil) mod.setCurrentDevice(nil)
d.gattDevice.Scan([]gatt.UUID{}, true) mod.gattDevice.Scan([]gatt.UUID{}, true)
} }
} }
func (d *BLERecon) onPeriphConnected(p gatt.Peripheral, err error) { func (mod *BLERecon) onPeriphConnected(p gatt.Peripheral, err error) {
if err != nil { if err != nil {
d.Warning("Connected to %s but with error: %s", p.ID(), err) mod.Warning("Connected to %s but with error: %s", p.ID(), err)
return return
} else if d.currDevice == nil { } else if mod.currDevice == nil {
// timed out // timed out
d.Warning("Connected to %s but after the timeout :(", p.ID()) mod.Warning("Connected to %s but after the timeout :(", p.ID())
return return
} }
d.connected = true mod.connected = true
defer func(per gatt.Peripheral) { defer func(per gatt.Peripheral) {
d.Info("Disconnecting from %s ...", per.ID()) mod.Info("Disconnecting from %s ...", per.ID())
per.Device().CancelConnection(per) per.Device().CancelConnection(per)
}(p) }(p)
d.Session.Events.Add("ble.device.connected", d.currDevice) mod.Session.Events.Add("ble.device.connected", mod.currDevice)
if err := p.SetMTU(500); err != nil { if err := p.SetMTU(500); err != nil {
d.Warning("Failed to set MTU: %s", err) mod.Warning("Failed to set MTU: %s", err)
} }
d.Info("Connected, enumerating all the things for %s!", p.ID()) mod.Info("Connected, enumerating all the things for %s!", p.ID())
services, err := p.DiscoverServices(nil) services, err := p.DiscoverServices(nil)
if err != nil { if err != nil {
d.Error("Error discovering services: %s", err) mod.Error("Error discovering services: %s", err)
return return
} }
d.showServices(p, services) mod.showServices(p, services)
} }

View file

@ -23,7 +23,7 @@ var (
blePresentInterval = time.Duration(30) * time.Second blePresentInterval = time.Duration(30) * time.Second
) )
func (d *BLERecon) getRow(dev *network.BLEDevice) []string { func (mod *BLERecon) getRow(dev *network.BLEDevice) []string {
address := network.NormalizeMac(dev.Device.ID()) address := network.NormalizeMac(dev.Device.ID())
vendor := dev.Vendor vendor := dev.Vendor
sinceSeen := time.Since(dev.LastSeen) sinceSeen := time.Since(dev.LastSeen)
@ -51,14 +51,14 @@ func (d *BLERecon) getRow(dev *network.BLEDevice) []string {
} }
} }
func (d *BLERecon) Show() error { func (mod *BLERecon) Show() error {
devices := d.Session.BLE.Devices() devices := mod.Session.BLE.Devices()
sort.Sort(ByBLERSSISorter(devices)) sort.Sort(ByBLERSSISorter(devices))
rows := make([][]string, 0) rows := make([][]string, 0)
for _, dev := range devices { for _, dev := range devices {
rows = append(rows, d.getRow(dev)) rows = append(rows, mod.getRow(dev))
} }
nrows := len(rows) nrows := len(rows)
@ -68,7 +68,7 @@ func (d *BLERecon) Show() error {
tui.Table(os.Stdout, columns, rows) tui.Table(os.Stdout, columns, rows)
} }
d.Session.Refresh() mod.Session.Refresh()
return nil return nil
} }
@ -124,15 +124,15 @@ func parseRawData(raw []byte) string {
return tui.Yellow(s) return tui.Yellow(s)
} }
func (d *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) { func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
columns := []string{"Handles", "Service > Characteristics", "Properties", "Data"} columns := []string{"Handles", "Service > Characteristics", "Properties", "Data"}
rows := make([][]string, 0) rows := make([][]string, 0)
wantsToWrite := d.writeUUID != nil wantsToWrite := mod.writeUUID != nil
foundToWrite := false foundToWrite := false
for _, svc := range services { for _, svc := range services {
d.Session.Events.Add("ble.device.service.discovered", svc) mod.Session.Events.Add("ble.device.service.discovered", svc)
name := svc.Name() name := svc.Name()
if name == "" { if name == "" {
@ -152,12 +152,12 @@ func (d *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
chars, err := p.DiscoverCharacteristics(nil, svc) chars, err := p.DiscoverCharacteristics(nil, svc)
if err != nil { if err != nil {
d.Error("Error while enumerating chars for service %s: %s", svc.UUID(), err) mod.Error("Error while enumerating chars for service %s: %s", svc.UUID(), err)
continue continue
} }
for _, ch := range chars { for _, ch := range chars {
d.Session.Events.Add("ble.device.characteristic.discovered", ch) mod.Session.Events.Add("ble.device.characteristic.discovered", ch)
name = ch.Name() name = ch.Name()
if name == "" { if name == "" {
@ -168,17 +168,17 @@ func (d *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
props, isReadable, isWritable, withResponse := parseProperties(ch) props, isReadable, isWritable, withResponse := parseProperties(ch)
if wantsToWrite && d.writeUUID.Equal(ch.UUID()) { if wantsToWrite && mod.writeUUID.Equal(ch.UUID()) {
foundToWrite = true foundToWrite = true
if isWritable { if isWritable {
d.Info("Writing %d bytes to characteristics %s ...", len(d.writeData), d.writeUUID) mod.Info("Writing %d bytes to characteristics %s ...", len(mod.writeData), mod.writeUUID)
} else { } else {
d.Warning("Attempt to write %d bytes to non writable characteristics %s ...", len(d.writeData), d.writeUUID) mod.Warning("Attempt to write %d bytes to non writable characteristics %s ...", len(mod.writeData), mod.writeUUID)
} }
err := p.WriteCharacteristic(ch, d.writeData, !withResponse) err := p.WriteCharacteristic(ch, mod.writeData, !withResponse)
if err != nil { if err != nil {
d.Error("Error while writing: %s", err) mod.Error("Error while writing: %s", err)
} }
} }
@ -204,9 +204,9 @@ func (d *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
} }
if wantsToWrite && !foundToWrite { if wantsToWrite && !foundToWrite {
d.Error("Writable characteristics %s not found.", d.writeUUID) mod.Error("Writable characteristics %s not found.", mod.writeUUID)
} else { } else {
tui.Table(os.Stdout, columns, rows) tui.Table(os.Stdout, columns, rows)
d.Session.Refresh() mod.Session.Refresh()
} }
} }

View file

@ -22,45 +22,45 @@ var defaultBLEServerOptions = []gatt.Option{
} }
*/ */
func NewBLERecon(s *session.Session) *BLERecon { func NewBLERecon(s *session.Session) *BLERecon {
d := &BLERecon{ mod := &BLERecon{
SessionModule: session.NewSessionModule("ble.recon", s), SessionModule: session.NewSessionModule("ble.recon", s),
} }
d.AddHandler(session.NewModuleHandler("ble.recon on", "", mod.AddHandler(session.NewModuleHandler("ble.recon on", "",
"Start Bluetooth Low Energy devices discovery.", "Start Bluetooth Low Energy devices discovery.",
func(args []string) error { func(args []string) error {
return session.ErrNotSupported return session.ErrNotSupported
})) }))
d.AddHandler(session.NewModuleHandler("ble.recon off", "", mod.AddHandler(session.NewModuleHandler("ble.recon off", "",
"Stop Bluetooth Low Energy devices discovery.", "Stop Bluetooth Low Energy devices discovery.",
func(args []string) error { func(args []string) error {
return session.ErrNotSupported return session.ErrNotSupported
})) }))
return d return mod
} }
func (d BLERecon) Name() string { func (mod BLERecon) Name() string {
return "ble.recon" return "ble.recon"
} }
func (d BLERecon) Description() string { func (mod BLERecon) Description() string {
return "Bluetooth Low Energy devices discovery." return "Bluetooth Low Energy devices discovery."
} }
func (d BLERecon) Author() string { func (mod BLERecon) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (d *BLERecon) Configure() (err error) { func (mod *BLERecon) Configure() (err error) {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (d *BLERecon) Start() error { func (mod *BLERecon) Start() error {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (d *BLERecon) Stop() error { func (mod *BLERecon) Stop() error {
return session.ErrNotSupported return session.ErrNotSupported
} }

View file

@ -21,56 +21,56 @@ type CapletsModule struct {
} }
func NewCapletsModule(s *session.Session) *CapletsModule { func NewCapletsModule(s *session.Session) *CapletsModule {
c := &CapletsModule{ mod := &CapletsModule{
SessionModule: session.NewSessionModule("caplets", s), SessionModule: session.NewSessionModule("caplets", s),
} }
c.AddHandler(session.NewModuleHandler("caplets.show", "", mod.AddHandler(session.NewModuleHandler("caplets.show", "",
"Show a list of installed caplets.", "Show a list of installed caplets.",
func(args []string) error { func(args []string) error {
return c.Show() return mod.Show()
})) }))
c.AddHandler(session.NewModuleHandler("caplets.paths", "", mod.AddHandler(session.NewModuleHandler("caplets.paths", "",
"Show a list caplet search paths.", "Show a list caplet search paths.",
func(args []string) error { func(args []string) error {
return c.Paths() return mod.Paths()
})) }))
c.AddHandler(session.NewModuleHandler("caplets.update", "", mod.AddHandler(session.NewModuleHandler("caplets.update", "",
"Install/updates the caplets.", "Install/updates the caplets.",
func(args []string) error { func(args []string) error {
return c.Update() return mod.Update()
})) }))
return c return mod
} }
func (c *CapletsModule) Name() string { func (mod *CapletsModule) Name() string {
return "caplets" return "caplets"
} }
func (c *CapletsModule) Description() string { func (mod *CapletsModule) Description() string {
return "A module to list and update caplets." return "A module to list and update caplets."
} }
func (c *CapletsModule) Author() string { func (mod *CapletsModule) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (c *CapletsModule) Configure() error { func (mod *CapletsModule) Configure() error {
return nil return nil
} }
func (c *CapletsModule) Stop() error { func (mod *CapletsModule) Stop() error {
return nil return nil
} }
func (c *CapletsModule) Start() error { func (mod *CapletsModule) Start() error {
return nil return nil
} }
func (c *CapletsModule) Show() error { func (mod *CapletsModule) Show() error {
caplets := caplets.List() caplets := caplets.List()
if len(caplets) == 0 { if len(caplets) == 0 {
return fmt.Errorf("no installed caplets on this system, use the caplets.update command to download them") return fmt.Errorf("no installed caplets on this system, use the caplets.update command to download them")
@ -96,7 +96,7 @@ func (c *CapletsModule) Show() error {
return nil return nil
} }
func (c *CapletsModule) Paths() error { func (mod *CapletsModule) Paths() error {
colNames := []string{ colNames := []string{
"Path", "Path",
} }
@ -112,9 +112,9 @@ func (c *CapletsModule) Paths() error {
return nil return nil
} }
func (c *CapletsModule) Update() error { func (mod *CapletsModule) Update() error {
if !fs.Exists(caplets.InstallBase) { if !fs.Exists(caplets.InstallBase) {
c.Info("creating caplets install path %s ...", caplets.InstallBase) mod.Info("creating caplets install path %s ...", caplets.InstallBase)
if err := os.MkdirAll(caplets.InstallBase, os.ModePerm); err != nil { if err := os.MkdirAll(caplets.InstallBase, os.ModePerm); err != nil {
return err return err
} }
@ -126,7 +126,7 @@ func (c *CapletsModule) Update() error {
} }
defer out.Close() defer out.Close()
c.Info("downloading caplets from %s ...", caplets.InstallArchive) mod.Info("downloading caplets from %s ...", caplets.InstallArchive)
resp, err := http.Get(caplets.InstallArchive) resp, err := http.Get(caplets.InstallArchive)
if err != nil { if err != nil {
@ -138,7 +138,7 @@ func (c *CapletsModule) Update() error {
return err return err
} }
c.Info("installing caplets to %s ...", caplets.InstallPath) mod.Info("installing caplets to %s ...", caplets.InstallPath)
if _, err = zip.Unzip("/tmp/caplets.zip", caplets.InstallBase); err != nil { if _, err = zip.Unzip("/tmp/caplets.zip", caplets.InstallBase); err != nil {
return err return err

View file

@ -36,93 +36,93 @@ type DHCP6Spoofer struct {
} }
func NewDHCP6Spoofer(s *session.Session) *DHCP6Spoofer { func NewDHCP6Spoofer(s *session.Session) *DHCP6Spoofer {
spoof := &DHCP6Spoofer{ mod := &DHCP6Spoofer{
SessionModule: session.NewSessionModule("dhcp6.spoof", s), SessionModule: session.NewSessionModule("dhcp6.spoof", s),
Handle: nil, Handle: nil,
waitGroup: &sync.WaitGroup{}, waitGroup: &sync.WaitGroup{},
} }
spoof.AddParam(session.NewStringParameter("dhcp6.spoof.domains", mod.AddParam(session.NewStringParameter("dhcp6.spoof.domains",
"microsoft.com, google.com, facebook.com, apple.com, twitter.com", "microsoft.com, google.com, facebook.com, apple.com, twitter.com",
``, ``,
"Comma separated values of domain names to spoof.")) "Comma separated values of domain names to spoof."))
spoof.AddHandler(session.NewModuleHandler("dhcp6.spoof on", "", mod.AddHandler(session.NewModuleHandler("dhcp6.spoof on", "",
"Start the DHCPv6 spoofer in the background.", "Start the DHCPv6 spoofer in the background.",
func(args []string) error { func(args []string) error {
return spoof.Start() return mod.Start()
})) }))
spoof.AddHandler(session.NewModuleHandler("dhcp6.spoof off", "", mod.AddHandler(session.NewModuleHandler("dhcp6.spoof off", "",
"Stop the DHCPv6 spoofer in the background.", "Stop the DHCPv6 spoofer in the background.",
func(args []string) error { func(args []string) error {
return spoof.Stop() return mod.Stop()
})) }))
return spoof return mod
} }
func (s DHCP6Spoofer) Name() string { func (mod DHCP6Spoofer) Name() string {
return "dhcp6.spoof" return "dhcp6.spoof"
} }
func (s DHCP6Spoofer) Description() string { func (mod DHCP6Spoofer) Description() string {
return "Replies to DHCPv6 messages, providing victims with a link-local IPv6 address and setting the attackers host as default DNS server (https://github.com/fox-it/mitm6/)." return "Replies to DHCPv6 messages, providing victims with a link-local IPv6 address and setting the attackers host as default DNS server (https://github.com/fox-it/mitm6/)."
} }
func (s DHCP6Spoofer) Author() string { func (mod DHCP6Spoofer) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (s *DHCP6Spoofer) Configure() error { func (mod *DHCP6Spoofer) Configure() error {
var err error var err error
if s.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} }
if s.Handle, err = pcap.OpenLive(s.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil { if mod.Handle, err = pcap.OpenLive(mod.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil {
return err return err
} }
err = s.Handle.SetBPFFilter("ip6 and udp") err = mod.Handle.SetBPFFilter("ip6 and udp")
if err != nil { if err != nil {
return err return err
} }
if err, s.Domains = s.ListParam("dhcp6.spoof.domains"); err != nil { if err, mod.Domains = mod.ListParam("dhcp6.spoof.domains"); err != nil {
return err return err
} }
s.RawDomains = packets.DHCP6EncodeList(s.Domains) mod.RawDomains = packets.DHCP6EncodeList(mod.Domains)
if s.DUID, err = dhcp6opts.NewDUIDLLT(1, time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC), s.Session.Interface.HW); err != nil { if mod.DUID, err = dhcp6opts.NewDUIDLLT(1, time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC), mod.Session.Interface.HW); err != nil {
return err return err
} else if s.DUIDRaw, err = s.DUID.MarshalBinary(); err != nil { } else if mod.DUIDRaw, err = mod.DUID.MarshalBinary(); err != nil {
return err return err
} }
if !s.Session.Firewall.IsForwardingEnabled() { if !mod.Session.Firewall.IsForwardingEnabled() {
s.Info("Enabling forwarding.") mod.Info("Enabling forwarding.")
s.Session.Firewall.EnableForwarding(true) mod.Session.Firewall.EnableForwarding(true)
} }
return nil return nil
} }
func (s *DHCP6Spoofer) dhcp6For(what dhcp6.MessageType, to dhcp6.Packet) (err error, p dhcp6.Packet) { func (mod *DHCP6Spoofer) dhcp6For(what dhcp6.MessageType, to dhcp6.Packet) (err error, p dhcp6.Packet) {
err, p = packets.DHCP6For(what, to, s.DUIDRaw) err, p = packets.DHCP6For(what, to, mod.DUIDRaw)
if err != nil { if err != nil {
return return
} }
p.Options.AddRaw(packets.DHCP6OptDNSServers, s.Session.Interface.IPv6) p.Options.AddRaw(packets.DHCP6OptDNSServers, mod.Session.Interface.IPv6)
p.Options.AddRaw(packets.DHCP6OptDNSDomains, s.RawDomains) p.Options.AddRaw(packets.DHCP6OptDNSDomains, mod.RawDomains)
return nil, p return nil, p
} }
func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet, target net.HardwareAddr) { func (mod *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet, target net.HardwareAddr) {
pip6 := pkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6) pip6 := pkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6)
fqdn := target.String() fqdn := target.String()
@ -130,29 +130,29 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet,
fqdn = string(raw[0]) fqdn = string(raw[0])
} }
s.Info("Got DHCPv6 Solicit request from %s (%s), sending spoofed advertisement for %d domains.", tui.Bold(fqdn), target, len(s.Domains)) mod.Info("Got DHCPv6 Solicit request from %s (%s), sending spoofed advertisement for %d domains.", tui.Bold(fqdn), target, len(mod.Domains))
err, adv := s.dhcp6For(dhcp6.MessageTypeAdvertise, solicit) err, adv := mod.dhcp6For(dhcp6.MessageTypeAdvertise, solicit)
if err != nil { if err != nil {
s.Error("%s", err) mod.Error("%s", err)
return return
} }
var solIANA dhcp6opts.IANA var solIANA dhcp6opts.IANA
if raw, found := solicit.Options[dhcp6.OptionIANA]; !found || len(raw) < 1 { if raw, found := solicit.Options[dhcp6.OptionIANA]; !found || len(raw) < 1 {
s.Error("Unexpected DHCPv6 packet, could not find IANA.") mod.Error("Unexpected DHCPv6 packet, could not find IANA.")
return return
} else if err := solIANA.UnmarshalBinary(raw[0]); err != nil { } else if err := solIANA.UnmarshalBinary(raw[0]); err != nil {
s.Error("Unexpected DHCPv6 packet, could not deserialize IANA.") mod.Error("Unexpected DHCPv6 packet, could not deserialize IANA.")
return return
} }
var ip net.IP var ip net.IP
if h, found := s.Session.Lan.Get(target.String()); found { if h, found := mod.Session.Lan.Get(target.String()); found {
ip = h.IP ip = h.IP
} else { } else {
s.Warning("Address %s not known, using random identity association address.", target.String()) mod.Warning("Address %s not known, using random identity association address.", target.String())
rand.Read(ip) rand.Read(ip)
} }
@ -160,13 +160,13 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet,
iaaddr, err := dhcp6opts.NewIAAddr(net.ParseIP(addr), 300*time.Second, 300*time.Second, nil) iaaddr, err := dhcp6opts.NewIAAddr(net.ParseIP(addr), 300*time.Second, 300*time.Second, nil)
if err != nil { if err != nil {
s.Error("Error creating IAAddr: %s", err) mod.Error("Error creating IAAddr: %s", err)
return return
} }
iaaddrRaw, err := iaaddr.MarshalBinary() iaaddrRaw, err := iaaddr.MarshalBinary()
if err != nil { if err != nil {
s.Error("Error serializing IAAddr: %s", err) mod.Error("Error serializing IAAddr: %s", err)
return return
} }
@ -174,7 +174,7 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet,
iana := dhcp6opts.NewIANA(solIANA.IAID, 200*time.Second, 250*time.Second, opts) iana := dhcp6opts.NewIANA(solIANA.IAID, 200*time.Second, 250*time.Second, opts)
ianaRaw, err := iana.MarshalBinary() ianaRaw, err := iana.MarshalBinary()
if err != nil { if err != nil {
s.Error("Error serializing IANA: %s", err) mod.Error("Error serializing IANA: %s", err)
return return
} }
@ -182,12 +182,12 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet,
rawAdv, err := adv.MarshalBinary() rawAdv, err := adv.MarshalBinary()
if err != nil { if err != nil {
s.Error("Error serializing advertisement packet: %s.", err) mod.Error("Error serializing advertisement packet: %s.", err)
return return
} }
eth := layers.Ethernet{ eth := layers.Ethernet{
SrcMAC: s.Session.Interface.HW, SrcMAC: mod.Session.Interface.HW,
DstMAC: target, DstMAC: target,
EthernetType: layers.EthernetTypeIPv6, EthernetType: layers.EthernetTypeIPv6,
} }
@ -196,7 +196,7 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet,
Version: 6, Version: 6,
NextHeader: layers.IPProtocolUDP, NextHeader: layers.IPProtocolUDP,
HopLimit: 64, HopLimit: 64,
SrcIP: s.Session.Interface.IPv6, SrcIP: mod.Session.Interface.IPv6,
DstIP: pip6.SrcIP, DstIP: pip6.SrcIP,
} }
@ -213,31 +213,31 @@ func (s *DHCP6Spoofer) dhcpAdvertise(pkt gopacket.Packet, solicit dhcp6.Packet,
err, raw := packets.Serialize(&eth, &ip6, &udp, &dhcp) err, raw := packets.Serialize(&eth, &ip6, &udp, &dhcp)
if err != nil { if err != nil {
s.Error("Error serializing packet: %s.", err) mod.Error("Error serializing packet: %s.", err)
return return
} }
s.Debug("Sending %d bytes of packet ...", len(raw)) mod.Debug("Sending %d bytes of packet ...", len(raw))
if err := s.Session.Queue.Send(raw); err != nil { if err := mod.Session.Queue.Send(raw); err != nil {
s.Error("Error sending packet: %s", err) mod.Error("Error sending packet: %s", err)
} }
} }
func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.Packet, target net.HardwareAddr) { func (mod *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.Packet, target net.HardwareAddr) {
s.Debug("Sending spoofed DHCPv6 reply to %s after its %s packet.", tui.Bold(target.String()), toType) mod.Debug("Sending spoofed DHCPv6 reply to %s after its %s packet.", tui.Bold(target.String()), toType)
err, reply := s.dhcp6For(dhcp6.MessageTypeReply, req) err, reply := mod.dhcp6For(dhcp6.MessageTypeReply, req)
if err != nil { if err != nil {
s.Error("%s", err) mod.Error("%s", err)
return return
} }
var reqIANA dhcp6opts.IANA var reqIANA dhcp6opts.IANA
if raw, found := req.Options[dhcp6.OptionIANA]; !found || len(raw) < 1 { if raw, found := req.Options[dhcp6.OptionIANA]; !found || len(raw) < 1 {
s.Error("Unexpected DHCPv6 packet, could not find IANA.") mod.Error("Unexpected DHCPv6 packet, could not find IANA.")
return return
} else if err := reqIANA.UnmarshalBinary(raw[0]); err != nil { } else if err := reqIANA.UnmarshalBinary(raw[0]); err != nil {
s.Error("Unexpected DHCPv6 packet, could not deserialize IANA.") mod.Error("Unexpected DHCPv6 packet, could not deserialize IANA.")
return return
} }
@ -245,7 +245,7 @@ func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.P
if raw, found := reqIANA.Options[dhcp6.OptionIAAddr]; found { if raw, found := reqIANA.Options[dhcp6.OptionIAAddr]; found {
reqIAddr = raw[0] reqIAddr = raw[0]
} else { } else {
s.Error("Unexpected DHCPv6 packet, could not deserialize request IANA IAAddr.") mod.Error("Unexpected DHCPv6 packet, could not deserialize request IANA IAAddr.")
return return
} }
@ -253,20 +253,20 @@ func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.P
iana := dhcp6opts.NewIANA(reqIANA.IAID, 200*time.Second, 250*time.Second, opts) iana := dhcp6opts.NewIANA(reqIANA.IAID, 200*time.Second, 250*time.Second, opts)
ianaRaw, err := iana.MarshalBinary() ianaRaw, err := iana.MarshalBinary()
if err != nil { if err != nil {
s.Error("Error serializing IANA: %s", err) mod.Error("Error serializing IANA: %s", err)
return return
} }
reply.Options.AddRaw(dhcp6.OptionIANA, ianaRaw) reply.Options.AddRaw(dhcp6.OptionIANA, ianaRaw)
rawAdv, err := reply.MarshalBinary() rawAdv, err := reply.MarshalBinary()
if err != nil { if err != nil {
s.Error("Error serializing advertisement packet: %s.", err) mod.Error("Error serializing advertisement packet: %s.", err)
return return
} }
pip6 := pkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6) pip6 := pkt.Layer(layers.LayerTypeIPv6).(*layers.IPv6)
eth := layers.Ethernet{ eth := layers.Ethernet{
SrcMAC: s.Session.Interface.HW, SrcMAC: mod.Session.Interface.HW,
DstMAC: target, DstMAC: target,
EthernetType: layers.EthernetTypeIPv6, EthernetType: layers.EthernetTypeIPv6,
} }
@ -275,7 +275,7 @@ func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.P
Version: 6, Version: 6,
NextHeader: layers.IPProtocolUDP, NextHeader: layers.IPProtocolUDP,
HopLimit: 64, HopLimit: 64,
SrcIP: s.Session.Interface.IPv6, SrcIP: mod.Session.Interface.IPv6,
DstIP: pip6.SrcIP, DstIP: pip6.SrcIP,
} }
@ -292,13 +292,13 @@ func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.P
err, raw := packets.Serialize(&eth, &ip6, &udp, &dhcp) err, raw := packets.Serialize(&eth, &ip6, &udp, &dhcp)
if err != nil { if err != nil {
s.Error("Error serializing packet: %s.", err) mod.Error("Error serializing packet: %s.", err)
return return
} }
s.Debug("Sending %d bytes of packet ...", len(raw)) mod.Debug("Sending %d bytes of packet ...", len(raw))
if err := s.Session.Queue.Send(raw); err != nil { if err := mod.Session.Queue.Send(raw); err != nil {
s.Error("Error sending packet: %s", err) mod.Error("Error sending packet: %s", err)
} }
if toType == "request" { if toType == "request" {
@ -307,26 +307,26 @@ func (s *DHCP6Spoofer) dhcpReply(toType string, pkt gopacket.Packet, req dhcp6.P
addr = net.IP(raw[0]) addr = net.IP(raw[0])
} }
if h, found := s.Session.Lan.Get(target.String()); found { if h, found := mod.Session.Lan.Get(target.String()); found {
s.Info("IPv6 address %s is now assigned to %s", addr.String(), h) mod.Info("IPv6 address %s is now assigned to %s", addr.String(), h)
} else { } else {
s.Info("IPv6 address %s is now assigned to %s", addr.String(), target) mod.Info("IPv6 address %s is now assigned to %s", addr.String(), target)
} }
} else { } else {
s.Debug("DHCPv6 renew sent to %s", target) mod.Debug("DHCPv6 renew sent to %s", target)
} }
} }
func (s *DHCP6Spoofer) duidMatches(dhcp dhcp6.Packet) bool { func (mod *DHCP6Spoofer) duidMatches(dhcp dhcp6.Packet) bool {
if raw, found := dhcp.Options[dhcp6.OptionServerID]; found && len(raw) >= 1 { if raw, found := dhcp.Options[dhcp6.OptionServerID]; found && len(raw) >= 1 {
if bytes.Equal(raw[0], s.DUIDRaw) { if bytes.Equal(raw[0], mod.DUIDRaw) {
return true return true
} }
} }
return false return false
} }
func (s *DHCP6Spoofer) onPacket(pkt gopacket.Packet) { func (mod *DHCP6Spoofer) onPacket(pkt gopacket.Packet) {
var dhcp dhcp6.Packet var dhcp dhcp6.Packet
var err error var err error
@ -341,46 +341,46 @@ func (s *DHCP6Spoofer) onPacket(pkt gopacket.Packet) {
switch dhcp.MessageType { switch dhcp.MessageType {
case dhcp6.MessageTypeSolicit: case dhcp6.MessageTypeSolicit:
s.dhcpAdvertise(pkt, dhcp, eth.SrcMAC) mod.dhcpAdvertise(pkt, dhcp, eth.SrcMAC)
case dhcp6.MessageTypeRequest: case dhcp6.MessageTypeRequest:
if s.duidMatches(dhcp) { if mod.duidMatches(dhcp) {
s.dhcpReply("request", pkt, dhcp, eth.SrcMAC) mod.dhcpReply("request", pkt, dhcp, eth.SrcMAC)
} }
case dhcp6.MessageTypeRenew: case dhcp6.MessageTypeRenew:
if s.duidMatches(dhcp) { if mod.duidMatches(dhcp) {
s.dhcpReply("renew", pkt, dhcp, eth.SrcMAC) mod.dhcpReply("renew", pkt, dhcp, eth.SrcMAC)
} }
} }
} }
} }
func (s *DHCP6Spoofer) Start() error { func (mod *DHCP6Spoofer) Start() error {
if err := s.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return s.SetRunning(true, func() { return mod.SetRunning(true, func() {
s.waitGroup.Add(1) mod.waitGroup.Add(1)
defer s.waitGroup.Done() defer mod.waitGroup.Done()
src := gopacket.NewPacketSource(s.Handle, s.Handle.LinkType()) src := gopacket.NewPacketSource(mod.Handle, mod.Handle.LinkType())
s.pktSourceChan = src.Packets() mod.pktSourceChan = src.Packets()
for packet := range s.pktSourceChan { for packet := range mod.pktSourceChan {
if !s.Running() { if !mod.Running() {
break break
} }
s.onPacket(packet) mod.onPacket(packet)
} }
}) })
} }
func (s *DHCP6Spoofer) Stop() error { func (mod *DHCP6Spoofer) Stop() error {
return s.SetRunning(false, func() { return mod.SetRunning(false, func() {
s.pktSourceChan <- nil mod.pktSourceChan <- nil
s.Handle.Close() mod.Handle.Close()
s.waitGroup.Wait() mod.waitGroup.Wait()
}) })
} }

View file

@ -26,7 +26,7 @@ type DNSSpoofer struct {
} }
func NewDNSSpoofer(s *session.Session) *DNSSpoofer { func NewDNSSpoofer(s *session.Session) *DNSSpoofer {
spoof := &DNSSpoofer{ mod := &DNSSpoofer{
SessionModule: session.NewSessionModule("dns.spoof", s), SessionModule: session.NewSessionModule("dns.spoof", s),
Handle: nil, Handle: nil,
All: false, All: false,
@ -34,120 +34,120 @@ func NewDNSSpoofer(s *session.Session) *DNSSpoofer {
waitGroup: &sync.WaitGroup{}, waitGroup: &sync.WaitGroup{},
} }
spoof.AddParam(session.NewStringParameter("dns.spoof.hosts", mod.AddParam(session.NewStringParameter("dns.spoof.hosts",
"", "",
"", "",
"If not empty, this hosts file will be used to map domains to IP addresses.")) "If not empty, this hosts file will be used to map domains to IP addresses."))
spoof.AddParam(session.NewStringParameter("dns.spoof.domains", mod.AddParam(session.NewStringParameter("dns.spoof.domains",
"", "",
"", "",
"Comma separated values of domain names to spoof.")) "Comma separated values of domain names to spoof."))
spoof.AddParam(session.NewStringParameter("dns.spoof.address", mod.AddParam(session.NewStringParameter("dns.spoof.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"IP address to map the domains to.")) "IP address to map the domains to."))
spoof.AddParam(session.NewBoolParameter("dns.spoof.all", mod.AddParam(session.NewBoolParameter("dns.spoof.all",
"false", "false",
"If true the module will reply to every DNS request, otherwise it will only reply to the one targeting the local pc.")) "If true the module will reply to every DNS request, otherwise it will only reply to the one targeting the local pc."))
spoof.AddHandler(session.NewModuleHandler("dns.spoof on", "", mod.AddHandler(session.NewModuleHandler("dns.spoof on", "",
"Start the DNS spoofer in the background.", "Start the DNS spoofer in the background.",
func(args []string) error { func(args []string) error {
return spoof.Start() return mod.Start()
})) }))
spoof.AddHandler(session.NewModuleHandler("dns.spoof off", "", mod.AddHandler(session.NewModuleHandler("dns.spoof off", "",
"Stop the DNS spoofer in the background.", "Stop the DNS spoofer in the background.",
func(args []string) error { func(args []string) error {
return spoof.Stop() return mod.Stop()
})) }))
return spoof return mod
} }
func (s DNSSpoofer) Name() string { func (mod DNSSpoofer) Name() string {
return "dns.spoof" return "dns.spoof"
} }
func (s DNSSpoofer) Description() string { func (mod DNSSpoofer) Description() string {
return "Replies to DNS messages with spoofed responses." return "Replies to DNS messages with spoofed responses."
} }
func (s DNSSpoofer) Author() string { func (mod DNSSpoofer) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (s *DNSSpoofer) Configure() error { func (mod *DNSSpoofer) Configure() error {
var err error var err error
var hostsFile string var hostsFile string
var domains []string var domains []string
var address net.IP var address net.IP
if s.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if s.Handle, err = pcap.OpenLive(s.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil { } else if mod.Handle, err = pcap.OpenLive(mod.Session.Interface.Name(), 65536, true, pcap.BlockForever); err != nil {
return err return err
} else if err = s.Handle.SetBPFFilter("udp"); err != nil { } else if err = mod.Handle.SetBPFFilter("udp"); err != nil {
return err return err
} else if err, s.All = s.BoolParam("dns.spoof.all"); err != nil { } else if err, mod.All = mod.BoolParam("dns.spoof.all"); err != nil {
return err return err
} else if err, address = s.IPParam("dns.spoof.address"); err != nil { } else if err, address = mod.IPParam("dns.spoof.address"); err != nil {
return err return err
} else if err, domains = s.ListParam("dns.spoof.domains"); err != nil { } else if err, domains = mod.ListParam("dns.spoof.domains"); err != nil {
return err return err
} else if err, hostsFile = s.StringParam("dns.spoof.hosts"); err != nil { } else if err, hostsFile = mod.StringParam("dns.spoof.hosts"); err != nil {
return err return err
} }
s.Hosts = Hosts{} mod.Hosts = Hosts{}
for _, domain := range domains { for _, domain := range domains {
s.Hosts = append(s.Hosts, NewHostEntry(domain, address)) mod.Hosts = append(mod.Hosts, NewHostEntry(domain, address))
} }
if hostsFile != "" { if hostsFile != "" {
s.Info("loading hosts from file %s ...", hostsFile) mod.Info("loading hosts from file %s ...", hostsFile)
if err, hosts := HostsFromFile(hostsFile); err != nil { if err, hosts := HostsFromFile(hostsFile); err != nil {
return fmt.Errorf("error reading hosts from file %s: %v", hostsFile, err) return fmt.Errorf("error reading hosts from file %s: %v", hostsFile, err)
} else { } else {
s.Hosts = append(s.Hosts, hosts...) mod.Hosts = append(mod.Hosts, hosts...)
} }
} }
if len(s.Hosts) == 0 { if len(mod.Hosts) == 0 {
return fmt.Errorf("at least dns.spoof.hosts or dns.spoof.domains must be filled") return fmt.Errorf("at least dns.spoof.hosts or dns.spoof.domains must be filled")
} }
for _, entry := range s.Hosts { for _, entry := range mod.Hosts {
s.Info("%s -> %s", entry.Host, entry.Address) mod.Info("%s -> %s", entry.Host, entry.Address)
} }
if !s.Session.Firewall.IsForwardingEnabled() { if !mod.Session.Firewall.IsForwardingEnabled() {
s.Info("enabling forwarding.") mod.Info("enabling forwarding.")
s.Session.Firewall.EnableForwarding(true) mod.Session.Firewall.EnableForwarding(true)
} }
return nil return nil
} }
func (s *DNSSpoofer) dnsReply(pkt gopacket.Packet, peth *layers.Ethernet, pudp *layers.UDP, domain string, address net.IP, req *layers.DNS, target net.HardwareAddr) { func (mod *DNSSpoofer) dnsReply(pkt gopacket.Packet, peth *layers.Ethernet, pudp *layers.UDP, domain string, address net.IP, req *layers.DNS, target net.HardwareAddr) {
redir := fmt.Sprintf("(->%s)", address.String()) redir := fmt.Sprintf("(->%s)", address.String())
who := target.String() who := target.String()
if t, found := s.Session.Lan.Get(target.String()); found { if t, found := mod.Session.Lan.Get(target.String()); found {
who = t.String() who = t.String()
} }
s.Info("sending spoofed DNS reply for %s %s to %s.", tui.Red(domain), tui.Dim(redir), tui.Bold(who)) mod.Info("sending spoofed DNS reply for %s %s to %s.", tui.Red(domain), tui.Dim(redir), tui.Bold(who))
var err error var err error
var src, dst net.IP var src, dst net.IP
nlayer := pkt.NetworkLayer() nlayer := pkt.NetworkLayer()
if nlayer == nil { if nlayer == nil {
s.Debug("missing network layer skipping packet.") mod.Debug("missing network layer skipping packet.")
return return
} }
@ -216,7 +216,7 @@ func (s *DNSSpoofer) dnsReply(pkt gopacket.Packet, peth *layers.Ethernet, pudp *
err, raw = packets.Serialize(&eth, &ip6, &udp, &dns) err, raw = packets.Serialize(&eth, &ip6, &udp, &dns)
if err != nil { if err != nil {
s.Error("error serializing packet: %s.", err) mod.Error("error serializing packet: %s.", err)
return return
} }
} else { } else {
@ -237,18 +237,18 @@ func (s *DNSSpoofer) dnsReply(pkt gopacket.Packet, peth *layers.Ethernet, pudp *
err, raw = packets.Serialize(&eth, &ip4, &udp, &dns) err, raw = packets.Serialize(&eth, &ip4, &udp, &dns)
if err != nil { if err != nil {
s.Error("error serializing packet: %s.", err) mod.Error("error serializing packet: %s.", err)
return return
} }
} }
s.Debug("sending %d bytes of packet ...", len(raw)) mod.Debug("sending %d bytes of packet ...", len(raw))
if err := s.Session.Queue.Send(raw); err != nil { if err := mod.Session.Queue.Send(raw); err != nil {
s.Error("error sending packet: %s", err) mod.Error("error sending packet: %s", err)
} }
} }
func (s *DNSSpoofer) onPacket(pkt gopacket.Packet) { func (mod *DNSSpoofer) onPacket(pkt gopacket.Packet) {
typeEth := pkt.Layer(layers.LayerTypeEthernet) typeEth := pkt.Layer(layers.LayerTypeEthernet)
typeUDP := pkt.Layer(layers.LayerTypeUDP) typeUDP := pkt.Layer(layers.LayerTypeUDP)
if typeEth == nil || typeUDP == nil { if typeEth == nil || typeUDP == nil {
@ -256,48 +256,48 @@ func (s *DNSSpoofer) onPacket(pkt gopacket.Packet) {
} }
eth := typeEth.(*layers.Ethernet) eth := typeEth.(*layers.Ethernet)
if s.All || bytes.Equal(eth.DstMAC, s.Session.Interface.HW) { if mod.All || bytes.Equal(eth.DstMAC, mod.Session.Interface.HW) {
dns, parsed := pkt.Layer(layers.LayerTypeDNS).(*layers.DNS) dns, parsed := pkt.Layer(layers.LayerTypeDNS).(*layers.DNS)
if parsed && dns.OpCode == layers.DNSOpCodeQuery && len(dns.Questions) > 0 && len(dns.Answers) == 0 { if parsed && dns.OpCode == layers.DNSOpCodeQuery && len(dns.Questions) > 0 && len(dns.Answers) == 0 {
udp := typeUDP.(*layers.UDP) udp := typeUDP.(*layers.UDP)
for _, q := range dns.Questions { for _, q := range dns.Questions {
qName := string(q.Name) qName := string(q.Name)
if address := s.Hosts.Resolve(qName); address != nil { if address := mod.Hosts.Resolve(qName); address != nil {
s.dnsReply(pkt, eth, udp, qName, address, dns, eth.SrcMAC) mod.dnsReply(pkt, eth, udp, qName, address, dns, eth.SrcMAC)
break break
} else { } else {
s.Debug("skipping domain %s", qName) mod.Debug("skipping domain %s", qName)
} }
} }
} }
} }
} }
func (s *DNSSpoofer) Start() error { func (mod *DNSSpoofer) Start() error {
if err := s.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return s.SetRunning(true, func() { return mod.SetRunning(true, func() {
s.waitGroup.Add(1) mod.waitGroup.Add(1)
defer s.waitGroup.Done() defer mod.waitGroup.Done()
src := gopacket.NewPacketSource(s.Handle, s.Handle.LinkType()) src := gopacket.NewPacketSource(mod.Handle, mod.Handle.LinkType())
s.pktSourceChan = src.Packets() mod.pktSourceChan = src.Packets()
for packet := range s.pktSourceChan { for packet := range mod.pktSourceChan {
if !s.Running() { if !mod.Running() {
break break
} }
s.onPacket(packet) mod.onPacket(packet)
} }
}) })
} }
func (s *DNSSpoofer) Stop() error { func (mod *DNSSpoofer) Stop() error {
return s.SetRunning(false, func() { return mod.SetRunning(false, func() {
s.pktSourceChan <- nil mod.pktSourceChan <- nil
s.Handle.Close() mod.Handle.Close()
s.waitGroup.Wait() mod.waitGroup.Wait()
}) })
} }

View file

@ -38,7 +38,7 @@ type EventsStream struct {
} }
func NewEventsStream(s *session.Session) *EventsStream { func NewEventsStream(s *session.Session) *EventsStream {
stream := &EventsStream{ mod := &EventsStream{
SessionModule: session.NewSessionModule("events.stream", s), SessionModule: session.NewSessionModule("events.stream", s),
output: os.Stdout, output: os.Stdout,
quit: make(chan bool), quit: make(chan bool),
@ -47,19 +47,19 @@ func NewEventsStream(s *session.Session) *EventsStream {
ignoreList: NewIgnoreList(), ignoreList: NewIgnoreList(),
} }
stream.AddHandler(session.NewModuleHandler("events.stream on", "", mod.AddHandler(session.NewModuleHandler("events.stream on", "",
"Start events stream.", "Start events stream.",
func(args []string) error { func(args []string) error {
return stream.Start() return mod.Start()
})) }))
stream.AddHandler(session.NewModuleHandler("events.stream off", "", mod.AddHandler(session.NewModuleHandler("events.stream off", "",
"Stop events stream.", "Stop events stream.",
func(args []string) error { func(args []string) error {
return stream.Stop() return mod.Stop()
})) }))
stream.AddHandler(session.NewModuleHandler("events.show LIMIT?", "events.show(\\s\\d+)?", mod.AddHandler(session.NewModuleHandler("events.show LIMIT?", "events.show(\\s\\d+)?",
"Show events stream.", "Show events stream.",
func(args []string) error { func(args []string) error {
limit := -1 limit := -1
@ -67,10 +67,10 @@ func NewEventsStream(s *session.Session) *EventsStream {
arg := str.Trim(args[0]) arg := str.Trim(args[0])
limit, _ = strconv.Atoi(arg) limit, _ = strconv.Atoi(arg)
} }
return stream.Show(limit) return mod.Show(limit)
})) }))
stream.AddHandler(session.NewModuleHandler("events.waitfor TAG TIMEOUT?", `events.waitfor ([^\s]+)([\s\d]*)`, mod.AddHandler(session.NewModuleHandler("events.waitfor TAG TIMEOUT?", `events.waitfor ([^\s]+)([\s\d]*)`,
"Wait for an event with the given tag either forever or for a timeout in seconds.", "Wait for an event with the given tag either forever or for a timeout in seconds.",
func(args []string) error { func(args []string) error {
tag := args[0] tag := args[0]
@ -85,163 +85,163 @@ func NewEventsStream(s *session.Session) *EventsStream {
timeout = n timeout = n
} }
} }
return stream.startWaitingFor(tag, timeout) return mod.startWaitingFor(tag, timeout)
})) }))
stream.AddHandler(session.NewModuleHandler("events.ignore FILTER", "events.ignore ([^\\s]+)", mod.AddHandler(session.NewModuleHandler("events.ignore FILTER", "events.ignore ([^\\s]+)",
"Events with an identifier matching this filter will not be shown (use multiple times to add more filters).", "Events with an identifier matching this filter will not be shown (use multiple times to add more filters).",
func(args []string) error { func(args []string) error {
return stream.ignoreList.Add(args[0]) return mod.ignoreList.Add(args[0])
})) }))
stream.AddHandler(session.NewModuleHandler("events.include FILTER", "events.include ([^\\s]+)", mod.AddHandler(session.NewModuleHandler("events.include FILTER", "events.include ([^\\s]+)",
"Used to remove filters passed with the events.ignore command.", "Used to remove filters passed with the events.ignore command.",
func(args []string) error { func(args []string) error {
return stream.ignoreList.Remove(args[0]) return mod.ignoreList.Remove(args[0])
})) }))
stream.AddHandler(session.NewModuleHandler("events.filters", "", mod.AddHandler(session.NewModuleHandler("events.filters", "",
"Print the list of filters used to ignore events.", "Print the list of filters used to ignore events.",
func(args []string) error { func(args []string) error {
if stream.ignoreList.Empty() { if mod.ignoreList.Empty() {
fmt.Printf("Ignore filters list is empty.\n") fmt.Printf("Ignore filters list is empty.\n")
} else { } else {
stream.ignoreList.RLock() mod.ignoreList.RLock()
defer stream.ignoreList.RUnlock() defer mod.ignoreList.RUnlock()
for _, filter := range stream.ignoreList.Filters() { for _, filter := range mod.ignoreList.Filters() {
fmt.Printf(" '%s'\n", string(filter)) fmt.Printf(" '%s'\n", string(filter))
} }
} }
return nil return nil
})) }))
stream.AddHandler(session.NewModuleHandler("events.clear", "", mod.AddHandler(session.NewModuleHandler("events.clear", "",
"Clear events stream.", "Clear events stream.",
func(args []string) error { func(args []string) error {
stream.Session.Events.Clear() mod.Session.Events.Clear()
return nil return nil
})) }))
stream.AddParam(session.NewStringParameter("events.stream.output", mod.AddParam(session.NewStringParameter("events.stream.output",
"", "",
"", "",
"If not empty, events will be written to this file instead of the standard output.")) "If not empty, events will be written to this file instead of the standard output."))
stream.AddParam(session.NewBoolParameter("events.stream.output.rotate", mod.AddParam(session.NewBoolParameter("events.stream.output.rotate",
"true", "true",
"If true will enable log rotation.")) "If true will enable log rotation."))
stream.AddParam(session.NewBoolParameter("events.stream.output.rotate.compress", mod.AddParam(session.NewBoolParameter("events.stream.output.rotate.compress",
"true", "true",
"If true will enable log rotation compression.")) "If true will enable log rotation compression."))
stream.AddParam(session.NewStringParameter("events.stream.output.rotate.how", mod.AddParam(session.NewStringParameter("events.stream.output.rotate.how",
"size", "size",
"(size|time)", "(size|time)",
"Rotate by 'size' or 'time'.")) "Rotate by 'size' or 'time'."))
stream.AddParam(session.NewStringParameter("events.stream.output.rotate.format", mod.AddParam(session.NewStringParameter("events.stream.output.rotate.format",
"2006-01-02 15:04:05", "2006-01-02 15:04:05",
"", "",
"Datetime format to use for log rotation file names.")) "Datetime format to use for log rotation file names."))
stream.AddParam(session.NewDecimalParameter("events.stream.output.rotate.when", mod.AddParam(session.NewDecimalParameter("events.stream.output.rotate.when",
"10", "10",
"File size (in MB) or time duration (in seconds) for log rotation.")) "File size (in MB) or time duration (in seconds) for log rotation."))
stream.AddParam(session.NewBoolParameter("events.stream.http.request.dump", mod.AddParam(session.NewBoolParameter("events.stream.http.request.dump",
"false", "false",
"If true all HTTP requests will be dumped.")) "If true all HTTP requests will be dumped."))
stream.AddParam(session.NewBoolParameter("events.stream.http.response.dump", mod.AddParam(session.NewBoolParameter("events.stream.http.response.dump",
"false", "false",
"If true all HTTP responses will be dumped.")) "If true all HTTP responses will be dumped."))
return stream return mod
} }
func (s EventsStream) Name() string { func (mod EventsStream) Name() string {
return "events.stream" return "events.stream"
} }
func (s EventsStream) Description() string { func (mod EventsStream) Description() string {
return "Print events as a continuous stream." return "Print events as a continuous stream."
} }
func (s EventsStream) Author() string { func (mod EventsStream) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (s *EventsStream) Configure() (err error) { func (mod *EventsStream) Configure() (err error) {
var output string var output string
if err, output = s.StringParam("events.stream.output"); err == nil { if err, output = mod.StringParam("events.stream.output"); err == nil {
if output == "" { if output == "" {
s.output = os.Stdout mod.output = os.Stdout
} else if s.outputName, err = fs.Expand(output); err == nil { } else if mod.outputName, err = fs.Expand(output); err == nil {
s.output, err = os.OpenFile(s.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) mod.output, err = os.OpenFile(mod.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
} }
} }
if err, s.rotation.Enabled = s.BoolParam("events.stream.output.rotate"); err != nil { if err, mod.rotation.Enabled = mod.BoolParam("events.stream.output.rotate"); err != nil {
return err return err
} else if err, s.rotation.Compress = s.BoolParam("events.stream.output.rotate.compress"); err != nil { } else if err, mod.rotation.Compress = mod.BoolParam("events.stream.output.rotate.compress"); err != nil {
return err return err
} else if err, s.rotation.Format = s.StringParam("events.stream.output.rotate.format"); err != nil { } else if err, mod.rotation.Format = mod.StringParam("events.stream.output.rotate.format"); err != nil {
return err return err
} else if err, s.rotation.How = s.StringParam("events.stream.output.rotate.how"); err != nil { } else if err, mod.rotation.How = mod.StringParam("events.stream.output.rotate.how"); err != nil {
return err return err
} else if err, s.rotation.Period = s.DecParam("events.stream.output.rotate.when"); err != nil { } else if err, mod.rotation.Period = mod.DecParam("events.stream.output.rotate.when"); err != nil {
return err return err
} }
if err, s.dumpHttpReqs = s.BoolParam("events.stream.http.request.dump"); err != nil { if err, mod.dumpHttpReqs = mod.BoolParam("events.stream.http.request.dump"); err != nil {
return err return err
} else if err, s.dumpHttpResp = s.BoolParam("events.stream.http.response.dump"); err != nil { } else if err, mod.dumpHttpResp = mod.BoolParam("events.stream.http.response.dump"); err != nil {
return err return err
} }
return err return err
} }
func (s *EventsStream) Start() error { func (mod *EventsStream) Start() error {
if err := s.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return s.SetRunning(true, func() { return mod.SetRunning(true, func() {
s.eventListener = s.Session.Events.Listen() mod.eventListener = mod.Session.Events.Listen()
defer s.Session.Events.Unlisten(s.eventListener) defer mod.Session.Events.Unlisten(mod.eventListener)
for { for {
var e session.Event var e session.Event
select { select {
case e = <-s.eventListener: case e = <-mod.eventListener:
if e.Tag == s.waitFor { if e.Tag == mod.waitFor {
s.waitFor = "" mod.waitFor = ""
s.waitChan <- &e mod.waitChan <- &e
} }
if !s.ignoreList.Ignored(e) { if !mod.ignoreList.Ignored(e) {
s.View(e, true) mod.View(e, true)
} }
case <-s.quit: case <-mod.quit:
return return
} }
} }
}) })
} }
func (s *EventsStream) Show(limit int) error { func (mod *EventsStream) Show(limit int) error {
events := s.Session.Events.Sorted() events := mod.Session.Events.Sorted()
num := len(events) num := len(events)
selected := []session.Event{} selected := []session.Event{}
for i := range events { for i := range events {
e := events[num-1-i] e := events[num-1-i]
if !s.ignoreList.Ignored(e) { if !mod.ignoreList.Ignored(e) {
selected = append(selected, e) selected = append(selected, e)
if len(selected) == limit { if len(selected) == limit {
break break
@ -252,43 +252,43 @@ func (s *EventsStream) Show(limit int) error {
if numSelected := len(selected); numSelected > 0 { if numSelected := len(selected); numSelected > 0 {
fmt.Println() fmt.Println()
for i := range selected { for i := range selected {
s.View(selected[numSelected-1-i], false) mod.View(selected[numSelected-1-i], false)
} }
s.Session.Refresh() mod.Session.Refresh()
} }
return nil return nil
} }
func (s *EventsStream) startWaitingFor(tag string, timeout int) error { func (mod *EventsStream) startWaitingFor(tag string, timeout int) error {
if timeout == 0 { if timeout == 0 {
s.Info("waiting for event %s ...", tui.Green(tag)) mod.Info("waiting for event %s ...", tui.Green(tag))
} else { } else {
s.Info("waiting for event %s for %d seconds ...", tui.Green(tag), timeout) mod.Info("waiting for event %s for %d seconds ...", tui.Green(tag), timeout)
go func() { go func() {
time.Sleep(time.Duration(timeout) * time.Second) time.Sleep(time.Duration(timeout) * time.Second)
s.waitFor = "" mod.waitFor = ""
s.waitChan <- nil mod.waitChan <- nil
}() }()
} }
s.waitFor = tag mod.waitFor = tag
event := <-s.waitChan event := <-mod.waitChan
if event == nil { if event == nil {
return fmt.Errorf("'events.waitFor %s %d' timed out.", tag, timeout) return fmt.Errorf("'events.waitFor %s %d' timed out.", tag, timeout)
} else { } else {
s.Debug("got event: %v", event) mod.Debug("got event: %v", event)
} }
return nil return nil
} }
func (s *EventsStream) Stop() error { func (mod *EventsStream) Stop() error {
return s.SetRunning(false, func() { return mod.SetRunning(false, func() {
s.quit <- true mod.quit <- true
if s.output != os.Stdout { if mod.output != os.Stdout {
s.output.Close() mod.output.Close()
} }
}) })
} }

View file

@ -20,15 +20,15 @@ import (
const eventTimeFormat = "15:04:05" const eventTimeFormat = "15:04:05"
func (s *EventsStream) viewLogEvent(e session.Event) { func (mod *EventsStream) viewLogEvent(e session.Event) {
fmt.Fprintf(s.output, "[%s] [%s] [%s] %s\n", fmt.Fprintf(mod.output, "[%s] [%s] [%s] %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
e.Label(), e.Label(),
e.Data.(session.LogMessage).Message) e.Data.(session.LogMessage).Message)
} }
func (s *EventsStream) viewEndpointEvent(e session.Event) { func (mod *EventsStream) viewEndpointEvent(e session.Event) {
t := e.Data.(*network.Endpoint) t := e.Data.(*network.Endpoint)
vend := "" vend := ""
name := "" name := ""
@ -44,7 +44,7 @@ func (s *EventsStream) viewEndpointEvent(e session.Event) {
} }
if e.Tag == "endpoint.new" { if e.Tag == "endpoint.new" {
fmt.Fprintf(s.output, "[%s] [%s] endpoint %s%s detected as %s%s.\n", fmt.Fprintf(mod.output, "[%s] [%s] endpoint %s%s detected as %s%s.\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
tui.Bold(t.IpAddress), tui.Bold(t.IpAddress),
@ -52,7 +52,7 @@ func (s *EventsStream) viewEndpointEvent(e session.Event) {
tui.Green(t.HwAddress), tui.Green(t.HwAddress),
tui.Dim(vend)) tui.Dim(vend))
} else if e.Tag == "endpoint.lost" { } else if e.Tag == "endpoint.lost" {
fmt.Fprintf(s.output, "[%s] [%s] endpoint %s%s %s%s lost.\n", fmt.Fprintf(mod.output, "[%s] [%s] endpoint %s%s %s%s lost.\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
tui.Red(t.IpAddress), tui.Red(t.IpAddress),
@ -60,82 +60,82 @@ func (s *EventsStream) viewEndpointEvent(e session.Event) {
tui.Green(t.HwAddress), tui.Green(t.HwAddress),
tui.Dim(vend)) tui.Dim(vend))
} else { } else {
fmt.Fprintf(s.output, "[%s] [%s] %s\n", fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
t.String()) t.String())
} }
} }
func (s *EventsStream) viewModuleEvent(e session.Event) { func (mod *EventsStream) viewModuleEvent(e session.Event) {
fmt.Fprintf(s.output, "[%s] [%s] %s\n", fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
e.Data) e.Data)
} }
func (s *EventsStream) viewSnifferEvent(e session.Event) { func (mod *EventsStream) viewSnifferEvent(e session.Event) {
if strings.HasPrefix(e.Tag, "net.sniff.http.") { if strings.HasPrefix(e.Tag, "net.sniff.http.") {
s.viewHttpEvent(e) mod.viewHttpEvent(e)
} else { } else {
fmt.Fprintf(s.output, "[%s] [%s] %s\n", fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
e.Data.(net_sniff.SnifferEvent).Message) e.Data.(net_sniff.SnifferEvent).Message)
} }
} }
func (s *EventsStream) viewSynScanEvent(e session.Event) { func (mod *EventsStream) viewSynScanEvent(e session.Event) {
se := e.Data.(syn_scan.SynScanEvent) se := e.Data.(syn_scan.SynScanEvent)
fmt.Fprintf(s.output, "[%s] [%s] found open port %d for %s\n", fmt.Fprintf(mod.output, "[%s] [%s] found open port %d for %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
se.Port, se.Port,
tui.Bold(se.Address)) tui.Bold(se.Address))
} }
func (s *EventsStream) viewUpdateEvent(e session.Event) { func (mod *EventsStream) viewUpdateEvent(e session.Event) {
update := e.Data.(*github.RepositoryRelease) update := e.Data.(*github.RepositoryRelease)
fmt.Fprintf(s.output, "[%s] [%s] an update to version %s is available at %s\n", fmt.Fprintf(mod.output, "[%s] [%s] an update to version %s is available at %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Bold(tui.Yellow(e.Tag)), tui.Bold(tui.Yellow(e.Tag)),
tui.Bold(*update.TagName), tui.Bold(*update.TagName),
*update.HTMLURL) *update.HTMLURL)
} }
func (s *EventsStream) doRotation() { func (mod *EventsStream) doRotation() {
if s.output == os.Stdout { if mod.output == os.Stdout {
return return
} else if !s.rotation.Enabled { } else if !mod.rotation.Enabled {
return return
} }
s.rotation.Lock() mod.rotation.Lock()
defer s.rotation.Unlock() defer mod.rotation.Unlock()
doRotate := false doRotate := false
if info, err := s.output.Stat(); err == nil { if info, err := mod.output.Stat(); err == nil {
if s.rotation.How == "size" { if mod.rotation.How == "size" {
doRotate = float64(info.Size()) >= float64(s.rotation.Period*1024*1024) doRotate = float64(info.Size()) >= float64(mod.rotation.Period*1024*1024)
} else if s.rotation.How == "time" { } else if mod.rotation.How == "time" {
doRotate = info.ModTime().Unix()%int64(s.rotation.Period) == 0 doRotate = info.ModTime().Unix()%int64(mod.rotation.Period) == 0
} }
} }
if doRotate { if doRotate {
var err error var err error
name := fmt.Sprintf("%s-%s", s.outputName, time.Now().Format(s.rotation.Format)) name := fmt.Sprintf("%s-%s", mod.outputName, time.Now().Format(mod.rotation.Format))
if err := s.output.Close(); err != nil { if err := mod.output.Close(); err != nil {
fmt.Printf("could not close log for rotation: %s\n", err) fmt.Printf("could not close log for rotation: %s\n", err)
return return
} }
if err := os.Rename(s.outputName, name); err != nil { if err := os.Rename(mod.outputName, name); err != nil {
fmt.Printf("could not rename %s to %s: %s\n", s.outputName, name, err) fmt.Printf("could not rename %s to %s: %s\n", mod.outputName, name, err)
} else if s.rotation.Compress { } else if mod.rotation.Compress {
zipName := fmt.Sprintf("%s.zip", name) zipName := fmt.Sprintf("%s.zip", name)
if err = zip.Files(zipName, []string{name}); err != nil { if err = zip.Files(zipName, []string{name}); err != nil {
fmt.Printf("error creating %s: %s", zipName, err) fmt.Printf("error creating %s: %s", zipName, err)
@ -144,37 +144,37 @@ func (s *EventsStream) doRotation() {
} }
} }
s.output, err = os.OpenFile(s.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) mod.output, err = os.OpenFile(mod.outputName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil { if err != nil {
fmt.Printf("could not open %s: %s", s.outputName, err) fmt.Printf("could not open %s: %s", mod.outputName, err)
} }
} }
} }
func (s *EventsStream) View(e session.Event, refresh bool) { func (mod *EventsStream) View(e session.Event, refresh bool) {
if e.Tag == "sys.log" { if e.Tag == "sys.log" {
s.viewLogEvent(e) mod.viewLogEvent(e)
} else if strings.HasPrefix(e.Tag, "endpoint.") { } else if strings.HasPrefix(e.Tag, "endpoint.") {
s.viewEndpointEvent(e) mod.viewEndpointEvent(e)
} else if strings.HasPrefix(e.Tag, "wifi.") { } else if strings.HasPrefix(e.Tag, "wifi.") {
s.viewWiFiEvent(e) mod.viewWiFiEvent(e)
} else if strings.HasPrefix(e.Tag, "ble.") { } else if strings.HasPrefix(e.Tag, "ble.") {
s.viewBLEEvent(e) mod.viewBLEEvent(e)
} else if strings.HasPrefix(e.Tag, "mod.") { } else if strings.HasPrefix(e.Tag, "mod.") {
s.viewModuleEvent(e) mod.viewModuleEvent(e)
} else if strings.HasPrefix(e.Tag, "net.sniff.") { } else if strings.HasPrefix(e.Tag, "net.sniff.") {
s.viewSnifferEvent(e) mod.viewSnifferEvent(e)
} else if e.Tag == "syn.scan" { } else if e.Tag == "syn.scan" {
s.viewSynScanEvent(e) mod.viewSynScanEvent(e)
} else if e.Tag == "update.available" { } else if e.Tag == "update.available" {
s.viewUpdateEvent(e) mod.viewUpdateEvent(e)
} else { } else {
fmt.Fprintf(s.output, "[%s] [%s] %v\n", e.Time.Format(eventTimeFormat), tui.Green(e.Tag), e) fmt.Fprintf(mod.output, "[%s] [%s] %v\n", e.Time.Format(eventTimeFormat), tui.Green(e.Tag), e)
} }
if refresh && s.output == os.Stdout { if refresh && mod.output == os.Stdout {
s.Session.Refresh() mod.Session.Refresh()
} }
s.doRotation() mod.doRotation()
} }

View file

@ -12,7 +12,7 @@ import (
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )
func (s *EventsStream) viewBLEEvent(e session.Event) { func (mod *EventsStream) viewBLEEvent(e session.Event) {
if e.Tag == "ble.device.new" { if e.Tag == "ble.device.new" {
dev := e.Data.(*network.BLEDevice) dev := e.Data.(*network.BLEDevice)
name := dev.Device.Name() name := dev.Device.Name()
@ -24,7 +24,7 @@ func (s *EventsStream) viewBLEEvent(e session.Event) {
vend = fmt.Sprintf(" (%s)", tui.Yellow(vend)) vend = fmt.Sprintf(" (%s)", tui.Yellow(vend))
} }
fmt.Fprintf(s.output, "[%s] [%s] new BLE device%s detected as %s%s %s.\n", fmt.Fprintf(mod.output, "[%s] [%s] new BLE device%s detected as %s%s %s.\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
name, name,
@ -42,7 +42,7 @@ func (s *EventsStream) viewBLEEvent(e session.Event) {
vend = fmt.Sprintf(" (%s)", tui.Yellow(vend)) vend = fmt.Sprintf(" (%s)", tui.Yellow(vend))
} }
fmt.Fprintf(s.output, "[%s] [%s] BLE device%s %s%s lost.\n", fmt.Fprintf(mod.output, "[%s] [%s] BLE device%s %s%s lost.\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
name, name,

View file

@ -6,6 +6,6 @@ import (
"github.com/bettercap/bettercap/session" "github.com/bettercap/bettercap/session"
) )
func (s *EventsStream) viewBLEEvent(e session.Event) { func (mod *EventsStream) viewBLEEvent(e session.Event) {
} }

View file

@ -20,8 +20,8 @@ var (
reJsonKey = regexp.MustCompile(`("[^"]+"):`) reJsonKey = regexp.MustCompile(`("[^"]+"):`)
) )
func (s *EventsStream) shouldDumpHttpRequest(req net_sniff.HTTPRequest) bool { func (mod *EventsStream) shouldDumpHttpRequest(req net_sniff.HTTPRequest) bool {
if s.dumpHttpReqs { if mod.dumpHttpReqs {
// dump all // dump all
return true return true
} else if req.Method != "GET" { } else if req.Method != "GET" {
@ -38,8 +38,8 @@ func (s *EventsStream) shouldDumpHttpRequest(req net_sniff.HTTPRequest) bool {
return false return false
} }
func (s *EventsStream) shouldDumpHttpResponse(res net_sniff.HTTPResponse) bool { func (mod *EventsStream) shouldDumpHttpResponse(res net_sniff.HTTPResponse) bool {
if s.dumpHttpResp { if mod.dumpHttpResp {
return true return true
} else if strings.Contains(res.ContentType, "text/plain") { } else if strings.Contains(res.ContentType, "text/plain") {
return true return true
@ -58,7 +58,7 @@ func (s *EventsStream) shouldDumpHttpResponse(res net_sniff.HTTPResponse) bool {
return false return false
} }
func (s *EventsStream) dumpForm(body []byte) string { func (mod *EventsStream) dumpForm(body []byte) string {
form := []string{} form := []string{}
for _, v := range strings.Split(string(body), "&") { for _, v := range strings.Split(string(body), "&") {
if strings.Contains(v, "=") { if strings.Contains(v, "=") {
@ -81,23 +81,23 @@ func (s *EventsStream) dumpForm(body []byte) string {
return "\n" + strings.Join(form, "&") + "\n" return "\n" + strings.Join(form, "&") + "\n"
} }
func (s *EventsStream) dumpText(body []byte) string { func (mod *EventsStream) dumpText(body []byte) string {
return "\n" + tui.Bold(tui.Red(string(body))) + "\n" return "\n" + tui.Bold(tui.Red(string(body))) + "\n"
} }
func (s *EventsStream) dumpGZIP(body []byte) string { func (mod *EventsStream) dumpGZIP(body []byte) string {
buffer := bytes.NewBuffer(body) buffer := bytes.NewBuffer(body)
uncompressed := bytes.Buffer{} uncompressed := bytes.Buffer{}
reader, err := gzip.NewReader(buffer) reader, err := gzip.NewReader(buffer)
if err != nil { if err != nil {
return s.dumpRaw(body) return mod.dumpRaw(body)
} else if _, err = uncompressed.ReadFrom(reader); err != nil { } else if _, err = uncompressed.ReadFrom(reader); err != nil {
return s.dumpRaw(body) return mod.dumpRaw(body)
} }
return s.dumpRaw(uncompressed.Bytes()) return mod.dumpRaw(uncompressed.Bytes())
} }
func (s *EventsStream) dumpJSON(body []byte) string { func (mod *EventsStream) dumpJSON(body []byte) string {
var buf bytes.Buffer var buf bytes.Buffer
var pretty string var pretty string
@ -110,25 +110,25 @@ func (s *EventsStream) dumpJSON(body []byte) string {
return "\n" + reJsonKey.ReplaceAllString(pretty, tui.Green(`$1:`)) + "\n" return "\n" + reJsonKey.ReplaceAllString(pretty, tui.Green(`$1:`)) + "\n"
} }
func (s *EventsStream) dumpXML(body []byte) string { func (mod *EventsStream) dumpXML(body []byte) string {
// TODO: indent xml // TODO: indent xml
return "\n" + string(body) + "\n" return "\n" + string(body) + "\n"
} }
func (s *EventsStream) dumpRaw(body []byte) string { func (mod *EventsStream) dumpRaw(body []byte) string {
return "\n" + hex.Dump(body) + "\n" return "\n" + hex.Dump(body) + "\n"
} }
func (s *EventsStream) viewHttpRequest(e session.Event) { func (mod *EventsStream) viewHttpRequest(e session.Event) {
se := e.Data.(net_sniff.SnifferEvent) se := e.Data.(net_sniff.SnifferEvent)
req := se.Data.(net_sniff.HTTPRequest) req := se.Data.(net_sniff.HTTPRequest)
fmt.Fprintf(s.output, "[%s] [%s] %s\n", fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
se.Message) se.Message)
if s.shouldDumpHttpRequest(req) { if mod.shouldDumpHttpRequest(req) {
dump := fmt.Sprintf("%s %s %s\n", tui.Bold(req.Method), req.URL, tui.Dim(req.Proto)) dump := fmt.Sprintf("%s %s %s\n", tui.Bold(req.Method), req.URL, tui.Dim(req.Proto))
dump += fmt.Sprintf("%s: %s\n", tui.Blue("Host"), tui.Yellow(req.Host)) dump += fmt.Sprintf("%s: %s\n", tui.Blue("Host"), tui.Yellow(req.Host))
for name, values := range req.Headers { for name, values := range req.Headers {
@ -139,34 +139,34 @@ func (s *EventsStream) viewHttpRequest(e session.Event) {
if req.Body != nil { if req.Body != nil {
if req.IsType("application/x-www-form-urlencoded") { if req.IsType("application/x-www-form-urlencoded") {
dump += s.dumpForm(req.Body) dump += mod.dumpForm(req.Body)
} else if req.IsType("text/plain") { } else if req.IsType("text/plain") {
dump += s.dumpText(req.Body) dump += mod.dumpText(req.Body)
} else if req.IsType("text/xml") { } else if req.IsType("text/xml") {
dump += s.dumpXML(req.Body) dump += mod.dumpXML(req.Body)
} else if req.IsType("gzip") { } else if req.IsType("gzip") {
dump += s.dumpGZIP(req.Body) dump += mod.dumpGZIP(req.Body)
} else if req.IsType("application/json") { } else if req.IsType("application/json") {
dump += s.dumpJSON(req.Body) dump += mod.dumpJSON(req.Body)
} else { } else {
dump += s.dumpRaw(req.Body) dump += mod.dumpRaw(req.Body)
} }
} }
fmt.Fprintf(s.output, "\n%s\n", dump) fmt.Fprintf(mod.output, "\n%s\n", dump)
} }
} }
func (s *EventsStream) viewHttpResponse(e session.Event) { func (mod *EventsStream) viewHttpResponse(e session.Event) {
se := e.Data.(net_sniff.SnifferEvent) se := e.Data.(net_sniff.SnifferEvent)
res := se.Data.(net_sniff.HTTPResponse) res := se.Data.(net_sniff.HTTPResponse)
fmt.Fprintf(s.output, "[%s] [%s] %s\n", fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
se.Message) se.Message)
if s.shouldDumpHttpResponse(res) { if mod.shouldDumpHttpResponse(res) {
dump := fmt.Sprintf("%s %s\n", tui.Dim(res.Protocol), res.Status) dump := fmt.Sprintf("%s %s\n", tui.Dim(res.Protocol), res.Status)
for name, values := range res.Headers { for name, values := range res.Headers {
for _, value := range values { for _, value := range values {
@ -177,22 +177,22 @@ func (s *EventsStream) viewHttpResponse(e session.Event) {
if res.Body != nil { if res.Body != nil {
// TODO: add more interesting response types // TODO: add more interesting response types
if res.IsType("text/plain") { if res.IsType("text/plain") {
dump += s.dumpText(res.Body) dump += mod.dumpText(res.Body)
} else if res.IsType("application/json") { } else if res.IsType("application/json") {
dump += s.dumpJSON(res.Body) dump += mod.dumpJSON(res.Body)
} else if res.IsType("text/xml") { } else if res.IsType("text/xml") {
dump += s.dumpXML(res.Body) dump += mod.dumpXML(res.Body)
} }
} }
fmt.Fprintf(s.output, "\n%s\n", dump) fmt.Fprintf(mod.output, "\n%s\n", dump)
} }
} }
func (s *EventsStream) viewHttpEvent(e session.Event) { func (mod *EventsStream) viewHttpEvent(e session.Event) {
if e.Tag == "net.sniff.http.request" { if e.Tag == "net.sniff.http.request" {
s.viewHttpRequest(e) mod.viewHttpRequest(e)
} else if e.Tag == "net.sniff.http.response" { } else if e.Tag == "net.sniff.http.response" {
s.viewHttpResponse(e) mod.viewHttpResponse(e)
} }
} }

View file

@ -11,7 +11,7 @@ import (
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )
func (s *EventsStream) viewWiFiApEvent(e session.Event) { func (mod *EventsStream) viewWiFiApEvent(e session.Event) {
ap := e.Data.(*network.AccessPoint) ap := e.Data.(*network.AccessPoint)
vend := "" vend := ""
if ap.Vendor != "" { if ap.Vendor != "" {
@ -23,7 +23,7 @@ func (s *EventsStream) viewWiFiApEvent(e session.Event) {
} }
if e.Tag == "wifi.ap.new" { if e.Tag == "wifi.ap.new" {
fmt.Fprintf(s.output, "[%s] [%s] wifi access point %s%s detected as %s%s.\n", fmt.Fprintf(mod.output, "[%s] [%s] wifi access point %s%s detected as %s%s.\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
tui.Bold(ap.ESSID()), tui.Bold(ap.ESSID()),
@ -31,21 +31,21 @@ func (s *EventsStream) viewWiFiApEvent(e session.Event) {
tui.Green(ap.BSSID()), tui.Green(ap.BSSID()),
tui.Dim(vend)) tui.Dim(vend))
} else if e.Tag == "wifi.ap.lost" { } else if e.Tag == "wifi.ap.lost" {
fmt.Fprintf(s.output, "[%s] [%s] wifi access point %s (%s) lost.\n", fmt.Fprintf(mod.output, "[%s] [%s] wifi access point %s (%s) lost.\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
tui.Red(ap.ESSID()), tui.Red(ap.ESSID()),
ap.BSSID()) ap.BSSID())
} else { } else {
fmt.Fprintf(s.output, "[%s] [%s] %s\n", fmt.Fprintf(mod.output, "[%s] [%s] %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
ap.String()) ap.String())
} }
} }
func (s *EventsStream) viewWiFiClientProbeEvent(e session.Event) { func (mod *EventsStream) viewWiFiClientProbeEvent(e session.Event) {
probe := e.Data.(wifi.WiFiProbeEvent) probe := e.Data.(wifi.ProbeEvent)
desc := "" desc := ""
if probe.FromAlias != "" { if probe.FromAlias != "" {
desc = fmt.Sprintf(" (%s)", probe.FromAlias) desc = fmt.Sprintf(" (%s)", probe.FromAlias)
@ -57,7 +57,7 @@ func (s *EventsStream) viewWiFiClientProbeEvent(e session.Event) {
rssi = fmt.Sprintf(" (%d dBm)", probe.RSSI) rssi = fmt.Sprintf(" (%d dBm)", probe.RSSI)
} }
fmt.Fprintf(s.output, "[%s] [%s] station %s%s is probing for SSID %s%s\n", fmt.Fprintf(mod.output, "[%s] [%s] station %s%s is probing for SSID %s%s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
probe.FromAddr.String(), probe.FromAddr.String(),
@ -66,14 +66,14 @@ func (s *EventsStream) viewWiFiClientProbeEvent(e session.Event) {
tui.Yellow(rssi)) tui.Yellow(rssi))
} }
func (s *EventsStream) viewWiFiHandshakeEvent(e session.Event) { func (mod *EventsStream) viewWiFiHandshakeEvent(e session.Event) {
hand := e.Data.(wifi.WiFiHandshakeEvent) hand := e.Data.(wifi.HandshakeEvent)
from := hand.Station.String() from := hand.Station.String()
to := hand.AP.String() to := hand.AP.String()
what := "handshake" what := "handshake"
if ap, found := s.Session.WiFi.Get(hand.AP.String()); found { if ap, found := mod.Session.WiFi.Get(hand.AP.String()); found {
to = fmt.Sprintf("%s (%s)", tui.Bold(ap.ESSID()), tui.Dim(ap.BSSID())) to = fmt.Sprintf("%s (%s)", tui.Bold(ap.ESSID()), tui.Dim(ap.BSSID()))
what = fmt.Sprintf("%s handshake", ap.Encryption) what = fmt.Sprintf("%s handshake", ap.Encryption)
} }
@ -82,7 +82,7 @@ func (s *EventsStream) viewWiFiHandshakeEvent(e session.Event) {
what = "RSN PMKID" what = "RSN PMKID"
} }
fmt.Fprintf(s.output, "[%s] [%s] captured %s -> %s %s to %s\n", fmt.Fprintf(mod.output, "[%s] [%s] captured %s -> %s %s to %s\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
from, from,
@ -91,20 +91,20 @@ func (s *EventsStream) viewWiFiHandshakeEvent(e session.Event) {
hand.File) hand.File)
} }
func (s *EventsStream) viewWiFiClientEvent(e session.Event) { func (mod *EventsStream) viewWiFiClientEvent(e session.Event) {
ce := e.Data.(wifi.WiFiClientEvent) ce := e.Data.(wifi.ClientEvent)
ce.Client.Alias = s.Session.Lan.GetAlias(ce.Client.BSSID()) ce.Client.Alias = mod.Session.Lan.GetAlias(ce.Client.BSSID())
if e.Tag == "wifi.client.new" { if e.Tag == "wifi.client.new" {
fmt.Fprintf(s.output, "[%s] [%s] new station %s detected for %s (%s)\n", fmt.Fprintf(mod.output, "[%s] [%s] new station %s detected for %s (%s)\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
ce.Client.String(), ce.Client.String(),
tui.Bold(ce.AP.ESSID()), tui.Bold(ce.AP.ESSID()),
tui.Dim(ce.AP.BSSID())) tui.Dim(ce.AP.BSSID()))
} else if e.Tag == "wifi.client.lost" { } else if e.Tag == "wifi.client.lost" {
fmt.Fprintf(s.output, "[%s] [%s] station %s disconnected from %s (%s)\n", fmt.Fprintf(mod.output, "[%s] [%s] station %s disconnected from %s (%s)\n",
e.Time.Format(eventTimeFormat), e.Time.Format(eventTimeFormat),
tui.Green(e.Tag), tui.Green(e.Tag),
ce.Client.String(), ce.Client.String(),
@ -113,16 +113,16 @@ func (s *EventsStream) viewWiFiClientEvent(e session.Event) {
} }
} }
func (s *EventsStream) viewWiFiEvent(e session.Event) { func (mod *EventsStream) viewWiFiEvent(e session.Event) {
if strings.HasPrefix(e.Tag, "wifi.ap.") { if strings.HasPrefix(e.Tag, "wifi.ap.") {
s.viewWiFiApEvent(e) mod.viewWiFiApEvent(e)
} else if e.Tag == "wifi.client.probe" { } else if e.Tag == "wifi.client.probe" {
s.viewWiFiClientProbeEvent(e) mod.viewWiFiClientProbeEvent(e)
} else if e.Tag == "wifi.client.handshake" { } else if e.Tag == "wifi.client.handshake" {
s.viewWiFiHandshakeEvent(e) mod.viewWiFiHandshakeEvent(e)
} else if e.Tag == "wifi.client.new" || e.Tag == "wifi.client.lost" { } else if e.Tag == "wifi.client.new" || e.Tag == "wifi.client.lost" {
s.viewWiFiClientEvent(e) mod.viewWiFiClientEvent(e)
} else { } else {
fmt.Fprintf(s.output, "[%s] [%s] %v\n", e.Time.Format(eventTimeFormat), tui.Green(e.Tag), e) fmt.Fprintf(mod.output, "[%s] [%s] %v\n", e.Time.Format(eventTimeFormat), tui.Green(e.Tag), e)
} }
} }

View file

@ -22,78 +22,78 @@ type GPS struct {
} }
func NewGPS(s *session.Session) *GPS { func NewGPS(s *session.Session) *GPS {
gps := &GPS{ mod := &GPS{
SessionModule: session.NewSessionModule("gps", s), SessionModule: session.NewSessionModule("gps", s),
serialPort: "/dev/ttyUSB0", serialPort: "/dev/ttyUSB0",
baudRate: 19200, baudRate: 19200,
} }
gps.AddParam(session.NewStringParameter("gps.device", mod.AddParam(session.NewStringParameter("gps.device",
gps.serialPort, mod.serialPort,
"", "",
"Serial device of the GPS hardware.")) "Serial device of the GPS hardware."))
gps.AddParam(session.NewIntParameter("gps.baudrate", mod.AddParam(session.NewIntParameter("gps.baudrate",
fmt.Sprintf("%d", gps.baudRate), fmt.Sprintf("%d", mod.baudRate),
"Baud rate of the GPS serial device.")) "Baud rate of the GPS serial device."))
gps.AddHandler(session.NewModuleHandler("gps on", "", mod.AddHandler(session.NewModuleHandler("gps on", "",
"Start acquiring from the GPS hardware.", "Start acquiring from the GPS hardware.",
func(args []string) error { func(args []string) error {
return gps.Start() return mod.Start()
})) }))
gps.AddHandler(session.NewModuleHandler("gps off", "", mod.AddHandler(session.NewModuleHandler("gps off", "",
"Stop acquiring from the GPS hardware.", "Stop acquiring from the GPS hardware.",
func(args []string) error { func(args []string) error {
return gps.Stop() return mod.Stop()
})) }))
gps.AddHandler(session.NewModuleHandler("gps.show", "", mod.AddHandler(session.NewModuleHandler("gps.show", "",
"Show the last coordinates returned by the GPS hardware.", "Show the last coordinates returned by the GPS hardware.",
func(args []string) error { func(args []string) error {
return gps.Show() return mod.Show()
})) }))
return gps return mod
} }
func (gps *GPS) Name() string { func (mod *GPS) Name() string {
return "gps" return "gps"
} }
func (gps *GPS) Description() string { func (mod *GPS) Description() string {
return "A module talking with GPS hardware on a serial interface." return "A module talking with GPS hardware on a serial interface."
} }
func (gps *GPS) Author() string { func (mod *GPS) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (gps *GPS) Configure() (err error) { func (mod *GPS) Configure() (err error) {
if gps.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, gps.serialPort = gps.StringParam("gps.device"); err != nil { } else if err, mod.serialPort = mod.StringParam("gps.device"); err != nil {
return err return err
} else if err, gps.baudRate = gps.IntParam("gps.baudrate"); err != nil { } else if err, mod.baudRate = mod.IntParam("gps.baudrate"); err != nil {
return err return err
} }
gps.serial, err = serial.OpenPort(&serial.Config{ mod.serial, err = serial.OpenPort(&serial.Config{
Name: gps.serialPort, Name: mod.serialPort,
Baud: gps.baudRate, Baud: mod.baudRate,
ReadTimeout: time.Second * 1, ReadTimeout: time.Second * 1,
}) })
return return
} }
func (gps *GPS) readLine() (line string, err error) { func (mod *GPS) readLine() (line string, err error) {
var n int var n int
b := make([]byte, 1) b := make([]byte, 1)
for { for {
if n, err = gps.serial.Read(b); err != nil { if n, err = mod.serial.Read(b); err != nil {
return return
} else if n == 1 { } else if n == 1 {
if b[0] == '\n' { if b[0] == '\n' {
@ -105,48 +105,48 @@ func (gps *GPS) readLine() (line string, err error) {
} }
} }
func (gps *GPS) Show() error { func (mod *GPS) Show() error {
fmt.Printf("latitude:%f longitude:%f quality:%s satellites:%d altitude:%f\n", fmt.Printf("latitude:%f longitude:%f quality:%s satellites:%d altitude:%f\n",
gps.Session.GPS.Latitude, mod.Session.GPS.Latitude,
gps.Session.GPS.Longitude, mod.Session.GPS.Longitude,
gps.Session.GPS.FixQuality, mod.Session.GPS.FixQuality,
gps.Session.GPS.NumSatellites, mod.Session.GPS.NumSatellites,
gps.Session.GPS.Altitude) mod.Session.GPS.Altitude)
gps.Session.Refresh() mod.Session.Refresh()
return nil return nil
} }
func (gps *GPS) Start() error { func (mod *GPS) Start() error {
if err := gps.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return gps.SetRunning(true, func() { return mod.SetRunning(true, func() {
defer gps.serial.Close() defer mod.serial.Close()
for gps.Running() { for mod.Running() {
if line, err := gps.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.GNGGA); ok {
gps.Session.GPS = m mod.Session.GPS = m
} }
} else { } else {
gps.Debug("error parsing line '%s': %s", line, err) mod.Debug("error parsing line '%s': %s", line, err)
} }
} else if err != io.EOF { } else if err != io.EOF {
gps.Warning("error while reading serial port: %s", err) mod.Warning("error while reading serial port: %s", err)
} }
} }
}) })
} }
func (gps *GPS) Stop() error { func (mod *GPS) Stop() error {
return gps.SetRunning(false, func() { return mod.SetRunning(false, func() {
// let the read fail and exit // let the read fail and exit
gps.serial.Close() mod.serial.Close()
}) })
} }

View file

@ -10,66 +10,66 @@ type HttpProxy struct {
} }
func NewHttpProxy(s *session.Session) *HttpProxy { func NewHttpProxy(s *session.Session) *HttpProxy {
p := &HttpProxy{ mod := &HttpProxy{
SessionModule: session.NewSessionModule("http.proxy", s), SessionModule: session.NewSessionModule("http.proxy", s),
proxy: NewHTTPProxy(s), proxy: NewHTTPProxy(s),
} }
p.AddParam(session.NewIntParameter("http.port", mod.AddParam(session.NewIntParameter("http.port",
"80", "80",
"HTTP port to redirect when the proxy is activated.")) "HTTP port to redirect when the proxy is activated."))
p.AddParam(session.NewStringParameter("http.proxy.address", mod.AddParam(session.NewStringParameter("http.proxy.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address to bind the HTTP proxy to.")) "Address to bind the HTTP proxy to."))
p.AddParam(session.NewIntParameter("http.proxy.port", mod.AddParam(session.NewIntParameter("http.proxy.port",
"8080", "8080",
"Port to bind the HTTP proxy to.")) "Port to bind the HTTP proxy to."))
p.AddParam(session.NewStringParameter("http.proxy.script", mod.AddParam(session.NewStringParameter("http.proxy.script",
"", "",
"", "",
"Path of a proxy JS script.")) "Path of a proxy JS script."))
p.AddParam(session.NewStringParameter("http.proxy.injectjs", mod.AddParam(session.NewStringParameter("http.proxy.injectjs",
"", "",
"", "",
"URL, path or javascript code to inject into every HTML page.")) "URL, path or javascript code to inject into every HTML page."))
p.AddParam(session.NewBoolParameter("http.proxy.sslstrip", mod.AddParam(session.NewBoolParameter("http.proxy.sslstrip",
"false", "false",
"Enable or disable SSL stripping.")) "Enable or disable SSL stripping."))
p.AddHandler(session.NewModuleHandler("http.proxy on", "", mod.AddHandler(session.NewModuleHandler("http.proxy on", "",
"Start HTTP proxy.", "Start HTTP proxy.",
func(args []string) error { func(args []string) error {
return p.Start() return mod.Start()
})) }))
p.AddHandler(session.NewModuleHandler("http.proxy off", "", mod.AddHandler(session.NewModuleHandler("http.proxy off", "",
"Stop HTTP proxy.", "Stop HTTP proxy.",
func(args []string) error { func(args []string) error {
return p.Stop() return mod.Stop()
})) }))
return p return mod
} }
func (p *HttpProxy) Name() string { func (mod *HttpProxy) Name() string {
return "http.proxy" return "http.proxy"
} }
func (p *HttpProxy) Description() string { func (mod *HttpProxy) Description() string {
return "A full featured HTTP proxy that can be used to inject malicious contents into webpages, all HTTP traffic will be redirected to it." return "A full featured HTTP proxy that can be used to inject malicious contents into webpages, all HTTP traffic will be redirected to it."
} }
func (p *HttpProxy) Author() string { func (mod *HttpProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (p *HttpProxy) Configure() error { func (mod *HttpProxy) Configure() error {
var err error var err error
var address string var address string
var proxyPort int var proxyPort int
@ -78,37 +78,37 @@ func (p *HttpProxy) Configure() error {
var stripSSL bool var stripSSL bool
var jsToInject string var jsToInject string
if p.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, address = p.StringParam("http.proxy.address"); err != nil { } else if err, address = mod.StringParam("http.proxy.address"); err != nil {
return err return err
} else if err, proxyPort = p.IntParam("http.proxy.port"); err != nil { } else if err, proxyPort = mod.IntParam("http.proxy.port"); err != nil {
return err return err
} else if err, httpPort = p.IntParam("http.port"); err != nil { } else if err, httpPort = mod.IntParam("http.port"); err != nil {
return err return err
} else if err, scriptPath = p.StringParam("http.proxy.script"); err != nil { } else if err, scriptPath = mod.StringParam("http.proxy.script"); err != nil {
return err return err
} else if err, stripSSL = p.BoolParam("http.proxy.sslstrip"); err != nil { } else if err, stripSSL = mod.BoolParam("http.proxy.sslstrip"); err != nil {
return err return err
} else if err, jsToInject = p.StringParam("http.proxy.injectjs"); err != nil { } else if err, jsToInject = mod.StringParam("http.proxy.injectjs"); err != nil {
return err return err
} }
return p.proxy.Configure(address, proxyPort, httpPort, scriptPath, jsToInject, stripSSL) return mod.proxy.Configure(address, proxyPort, httpPort, scriptPath, jsToInject, stripSSL)
} }
func (p *HttpProxy) Start() error { func (mod *HttpProxy) Start() error {
if err := p.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return p.SetRunning(true, func() { return mod.SetRunning(true, func() {
p.proxy.Start() mod.proxy.Start()
}) })
} }
func (p *HttpProxy) Stop() error { func (mod *HttpProxy) Stop() error {
return p.SetRunning(false, func() { return mod.SetRunning(false, func() {
p.proxy.Stop() mod.proxy.Stop()
}) })
} }

View file

@ -18,63 +18,63 @@ type HttpServer struct {
} }
func NewHttpServer(s *session.Session) *HttpServer { func NewHttpServer(s *session.Session) *HttpServer {
httpd := &HttpServer{ mod := &HttpServer{
SessionModule: session.NewSessionModule("http.server", s), SessionModule: session.NewSessionModule("http.server", s),
server: &http.Server{}, server: &http.Server{},
} }
httpd.AddParam(session.NewStringParameter("http.server.path", mod.AddParam(session.NewStringParameter("http.server.path",
".", ".",
"", "",
"Server folder.")) "Server folder."))
httpd.AddParam(session.NewStringParameter("http.server.address", mod.AddParam(session.NewStringParameter("http.server.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address to bind the http server to.")) "Address to bind the http server to."))
httpd.AddParam(session.NewIntParameter("http.server.port", mod.AddParam(session.NewIntParameter("http.server.port",
"80", "80",
"Port to bind the http server to.")) "Port to bind the http server to."))
httpd.AddHandler(session.NewModuleHandler("http.server on", "", mod.AddHandler(session.NewModuleHandler("http.server on", "",
"Start httpd server.", "Start httpd server.",
func(args []string) error { func(args []string) error {
return httpd.Start() return mod.Start()
})) }))
httpd.AddHandler(session.NewModuleHandler("http.server off", "", mod.AddHandler(session.NewModuleHandler("http.server off", "",
"Stop httpd server.", "Stop httpd server.",
func(args []string) error { func(args []string) error {
return httpd.Stop() return mod.Stop()
})) }))
return httpd return mod
} }
func (httpd *HttpServer) Name() string { func (mod *HttpServer) Name() string {
return "http.server" return "http.server"
} }
func (httpd *HttpServer) Description() string { func (mod *HttpServer) Description() string {
return "A simple HTTP server, to be used to serve files and scripts across the network." return "A simple HTTP server, to be used to serve files and scripts across the network."
} }
func (httpd *HttpServer) Author() string { func (mod *HttpServer) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (httpd *HttpServer) Configure() error { func (mod *HttpServer) Configure() error {
var err error var err error
var path string var path string
var address string var address string
var port int var port int
if httpd.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} }
if err, path = httpd.StringParam("http.server.path"); err != nil { if err, path = mod.StringParam("http.server.path"); err != nil {
return err return err
} }
@ -82,43 +82,43 @@ func (httpd *HttpServer) Configure() error {
fileServer := http.FileServer(http.Dir(path)) fileServer := http.FileServer(http.Dir(path))
router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpd.Info("%s %s %s%s", tui.Bold(strings.Split(r.RemoteAddr, ":")[0]), r.Method, r.Host, r.URL.Path) mod.Info("%s %s %s%s", tui.Bold(strings.Split(r.RemoteAddr, ":")[0]), r.Method, r.Host, r.URL.Path)
fileServer.ServeHTTP(w, r) fileServer.ServeHTTP(w, r)
})) }))
httpd.server.Handler = router mod.server.Handler = router
if err, address = httpd.StringParam("http.server.address"); err != nil { if err, address = mod.StringParam("http.server.address"); err != nil {
return err return err
} }
if err, port = httpd.IntParam("http.server.port"); err != nil { if err, port = mod.IntParam("http.server.port"); err != nil {
return err return err
} }
httpd.server.Addr = fmt.Sprintf("%s:%d", address, port) mod.server.Addr = fmt.Sprintf("%s:%d", address, port)
return nil return nil
} }
func (httpd *HttpServer) Start() error { func (mod *HttpServer) Start() error {
if err := httpd.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return httpd.SetRunning(true, func() { return mod.SetRunning(true, func() {
var err error var err error
httpd.Info("starting on http://%s", httpd.server.Addr) mod.Info("starting on http://%s", mod.server.Addr)
if err = httpd.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { if err = mod.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
panic(err) panic(err)
} }
}) })
} }
func (httpd *HttpServer) Stop() error { func (mod *HttpServer) Stop() error {
return httpd.SetRunning(false, func() { return mod.SetRunning(false, func() {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel() defer cancel()
httpd.server.Shutdown(ctx) mod.server.Shutdown(ctx)
}) })
} }

View file

@ -14,78 +14,78 @@ type HttpsProxy struct {
} }
func NewHttpsProxy(s *session.Session) *HttpsProxy { func NewHttpsProxy(s *session.Session) *HttpsProxy {
p := &HttpsProxy{ mod := &HttpsProxy{
SessionModule: session.NewSessionModule("https.proxy", s), SessionModule: session.NewSessionModule("https.proxy", s),
proxy: http_proxy.NewHTTPProxy(s), proxy: http_proxy.NewHTTPProxy(s),
} }
p.AddParam(session.NewIntParameter("https.port", mod.AddParam(session.NewIntParameter("https.port",
"443", "443",
"HTTPS port to redirect when the proxy is activated.")) "HTTPS port to redirect when the proxy is activated."))
p.AddParam(session.NewStringParameter("https.proxy.address", mod.AddParam(session.NewStringParameter("https.proxy.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address to bind the HTTPS proxy to.")) "Address to bind the HTTPS proxy to."))
p.AddParam(session.NewIntParameter("https.proxy.port", mod.AddParam(session.NewIntParameter("https.proxy.port",
"8083", "8083",
"Port to bind the HTTPS proxy to.")) "Port to bind the HTTPS proxy to."))
p.AddParam(session.NewBoolParameter("https.proxy.sslstrip", mod.AddParam(session.NewBoolParameter("https.proxy.sslstrip",
"false", "false",
"Enable or disable SSL stripping.")) "Enable or disable SSL stripping."))
p.AddParam(session.NewStringParameter("https.proxy.injectjs", mod.AddParam(session.NewStringParameter("https.proxy.injectjs",
"", "",
"", "",
"URL, path or javascript code to inject into every HTML page.")) "URL, path or javascript code to inject into every HTML page."))
p.AddParam(session.NewStringParameter("https.proxy.certificate", mod.AddParam(session.NewStringParameter("https.proxy.certificate",
"~/.bettercap-ca.cert.pem", "~/.bettercap-ca.cert.pem",
"", "",
"HTTPS proxy certification authority TLS certificate file.")) "HTTPS proxy certification authority TLS certificate file."))
p.AddParam(session.NewStringParameter("https.proxy.key", mod.AddParam(session.NewStringParameter("https.proxy.key",
"~/.bettercap-ca.key.pem", "~/.bettercap-ca.key.pem",
"", "",
"HTTPS proxy certification authority TLS key file.")) "HTTPS proxy certification authority TLS key file."))
tls.CertConfigToModule("https.proxy", &p.SessionModule, tls.DefaultSpoofConfig) tls.CertConfigToModule("https.proxy", &mod.SessionModule, tls.DefaultSpoofConfig)
p.AddParam(session.NewStringParameter("https.proxy.script", mod.AddParam(session.NewStringParameter("https.proxy.script",
"", "",
"", "",
"Path of a proxy JS script.")) "Path of a proxy JS script."))
p.AddHandler(session.NewModuleHandler("https.proxy on", "", mod.AddHandler(session.NewModuleHandler("https.proxy on", "",
"Start HTTPS proxy.", "Start HTTPS proxy.",
func(args []string) error { func(args []string) error {
return p.Start() return mod.Start()
})) }))
p.AddHandler(session.NewModuleHandler("https.proxy off", "", mod.AddHandler(session.NewModuleHandler("https.proxy off", "",
"Stop HTTPS proxy.", "Stop HTTPS proxy.",
func(args []string) error { func(args []string) error {
return p.Stop() return mod.Stop()
})) }))
return p return mod
} }
func (p *HttpsProxy) Name() string { func (mod *HttpsProxy) Name() string {
return "https.proxy" return "https.proxy"
} }
func (p *HttpsProxy) Description() string { func (mod *HttpsProxy) Description() string {
return "A full featured HTTPS proxy that can be used to inject malicious contents into webpages, all HTTPS traffic will be redirected to it." return "A full featured HTTPS proxy that can be used to inject malicious contents into webpages, all HTTPS traffic will be redirected to it."
} }
func (p *HttpsProxy) Author() string { func (mod *HttpsProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (p *HttpsProxy) Configure() error { func (mod *HttpsProxy) Configure() error {
var err error var err error
var address string var address string
var proxyPort int var proxyPort int
@ -96,62 +96,62 @@ func (p *HttpsProxy) Configure() error {
var stripSSL bool var stripSSL bool
var jsToInject string var jsToInject string
if p.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, address = p.StringParam("https.proxy.address"); err != nil { } else if err, address = mod.StringParam("https.proxy.address"); err != nil {
return err return err
} else if err, proxyPort = p.IntParam("https.proxy.port"); err != nil { } else if err, proxyPort = mod.IntParam("https.proxy.port"); err != nil {
return err return err
} else if err, httpPort = p.IntParam("https.port"); err != nil { } else if err, httpPort = mod.IntParam("https.port"); err != nil {
return err return err
} else if err, stripSSL = p.BoolParam("https.proxy.sslstrip"); err != nil { } else if err, stripSSL = mod.BoolParam("https.proxy.sslstrip"); err != nil {
return err return err
} else if err, certFile = p.StringParam("https.proxy.certificate"); err != nil { } else if err, certFile = mod.StringParam("https.proxy.certificate"); err != nil {
return err return err
} else if certFile, err = fs.Expand(certFile); err != nil { } else if certFile, err = fs.Expand(certFile); err != nil {
return err return err
} else if err, keyFile = p.StringParam("https.proxy.key"); err != nil { } else if err, keyFile = mod.StringParam("https.proxy.key"); err != nil {
return err return err
} else if keyFile, err = fs.Expand(keyFile); err != nil { } else if keyFile, err = fs.Expand(keyFile); err != nil {
return err return err
} else if err, scriptPath = p.StringParam("https.proxy.script"); err != nil { } else if err, scriptPath = mod.StringParam("https.proxy.script"); err != nil {
return err return err
} else if err, jsToInject = p.StringParam("https.proxy.injectjs"); err != nil { } else if err, jsToInject = mod.StringParam("https.proxy.injectjs"); err != nil {
return err return err
} }
if !fs.Exists(certFile) || !fs.Exists(keyFile) { if !fs.Exists(certFile) || !fs.Exists(keyFile) {
err, cfg := tls.CertConfigFromModule("https.proxy", p.SessionModule) err, cfg := tls.CertConfigFromModule("https.proxy", mod.SessionModule)
if err != nil { if err != nil {
return err return err
} }
p.Debug("%+v", cfg) mod.Debug("%+v", cfg)
p.Info("generating proxy certification authority TLS key to %s", keyFile) mod.Info("generating proxy certification authority TLS key to %s", keyFile)
p.Info("generating proxy certification authority TLS certificate to %s", certFile) mod.Info("generating proxy certification authority TLS certificate to %s", certFile)
if err := tls.Generate(cfg, certFile, keyFile); err != nil { if err := tls.Generate(cfg, certFile, keyFile); err != nil {
return err return err
} }
} else { } else {
p.Info("loading proxy certification authority TLS key from %s", keyFile) mod.Info("loading proxy certification authority TLS key from %s", keyFile)
p.Info("loading proxy certification authority TLS certificate from %s", certFile) mod.Info("loading proxy certification authority TLS certificate from %s", certFile)
} }
return p.proxy.ConfigureTLS(address, proxyPort, httpPort, scriptPath, certFile, keyFile, jsToInject, stripSSL) return mod.proxy.ConfigureTLS(address, proxyPort, httpPort, scriptPath, certFile, keyFile, jsToInject, stripSSL)
} }
func (p *HttpsProxy) Start() error { func (mod *HttpsProxy) Start() error {
if err := p.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return p.SetRunning(true, func() { return mod.SetRunning(true, func() {
p.proxy.Start() mod.proxy.Start()
}) })
} }
func (p *HttpsProxy) Stop() error { func (mod *HttpsProxy) Stop() error {
return p.SetRunning(false, func() { return mod.SetRunning(false, func() {
p.proxy.Stop() mod.proxy.Stop()
}) })
} }

View file

@ -22,65 +22,65 @@ type HttpsServer struct {
} }
func NewHttpsServer(s *session.Session) *HttpsServer { func NewHttpsServer(s *session.Session) *HttpsServer {
httpd := &HttpsServer{ mod := &HttpsServer{
SessionModule: session.NewSessionModule("https.server", s), SessionModule: session.NewSessionModule("https.server", s),
server: &http.Server{}, server: &http.Server{},
} }
httpd.AddParam(session.NewStringParameter("https.server.path", mod.AddParam(session.NewStringParameter("https.server.path",
".", ".",
"", "",
"Server folder.")) "Server folder."))
httpd.AddParam(session.NewStringParameter("https.server.address", mod.AddParam(session.NewStringParameter("https.server.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address to bind the http server to.")) "Address to bind the http server to."))
httpd.AddParam(session.NewIntParameter("https.server.port", mod.AddParam(session.NewIntParameter("https.server.port",
"443", "443",
"Port to bind the http server to.")) "Port to bind the http server to."))
httpd.AddParam(session.NewStringParameter("https.server.certificate", mod.AddParam(session.NewStringParameter("https.server.certificate",
"~/.bettercap-https.cert.pem", "~/.bettercap-https.cert.pem",
"", "",
"TLS certificate file (will be auto generated if filled but not existing).")) "TLS certificate file (will be auto generated if filled but not existing)."))
httpd.AddParam(session.NewStringParameter("https.server.key", mod.AddParam(session.NewStringParameter("https.server.key",
"~/.bettercap-https.key.pem", "~/.bettercap-https.key.pem",
"", "",
"TLS key file (will be auto generated if filled but not existing).")) "TLS key file (will be auto generated if filled but not existing)."))
tls.CertConfigToModule("https.server", &httpd.SessionModule, tls.DefaultLegitConfig) tls.CertConfigToModule("https.server", &mod.SessionModule, tls.DefaultLegitConfig)
httpd.AddHandler(session.NewModuleHandler("https.server on", "", mod.AddHandler(session.NewModuleHandler("https.server on", "",
"Start https server.", "Start https server.",
func(args []string) error { func(args []string) error {
return httpd.Start() return mod.Start()
})) }))
httpd.AddHandler(session.NewModuleHandler("https.server off", "", mod.AddHandler(session.NewModuleHandler("https.server off", "",
"Stop https server.", "Stop https server.",
func(args []string) error { func(args []string) error {
return httpd.Stop() return mod.Stop()
})) }))
return httpd return mod
} }
func (httpd *HttpsServer) Name() string { func (mod *HttpsServer) Name() string {
return "https.server" return "https.server"
} }
func (httpd *HttpsServer) Description() string { func (mod *HttpsServer) Description() string {
return "A simple HTTPS server, to be used to serve files and scripts across the network." return "A simple HTTPS server, to be used to serve files and scripts across the network."
} }
func (httpd *HttpsServer) Author() string { func (mod *HttpsServer) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (httpd *HttpsServer) Configure() error { func (mod *HttpsServer) Configure() error {
var err error var err error
var path string var path string
var address string var address string
@ -88,11 +88,11 @@ func (httpd *HttpsServer) Configure() error {
var certFile string var certFile string
var keyFile string var keyFile string
if httpd.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} }
if err, path = httpd.StringParam("https.server.path"); err != nil { if err, path = mod.StringParam("https.server.path"); err != nil {
return err return err
} }
@ -100,74 +100,74 @@ func (httpd *HttpsServer) Configure() error {
fileServer := http.FileServer(http.Dir(path)) fileServer := http.FileServer(http.Dir(path))
router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpd.Info("%s %s %s%s", tui.Bold(strings.Split(r.RemoteAddr, ":")[0]), r.Method, r.Host, r.URL.Path) mod.Info("%s %s %s%s", tui.Bold(strings.Split(r.RemoteAddr, ":")[0]), r.Method, r.Host, r.URL.Path)
fileServer.ServeHTTP(w, r) fileServer.ServeHTTP(w, r)
})) }))
httpd.server.Handler = router mod.server.Handler = router
if err, address = httpd.StringParam("https.server.address"); err != nil { if err, address = mod.StringParam("https.server.address"); err != nil {
return err return err
} }
if err, port = httpd.IntParam("https.server.port"); err != nil { if err, port = mod.IntParam("https.server.port"); err != nil {
return err return err
} }
httpd.server.Addr = fmt.Sprintf("%s:%d", address, port) mod.server.Addr = fmt.Sprintf("%s:%d", address, port)
if err, certFile = httpd.StringParam("https.server.certificate"); err != nil { if err, certFile = mod.StringParam("https.server.certificate"); err != nil {
return err return err
} else if certFile, err = fs.Expand(certFile); err != nil { } else if certFile, err = fs.Expand(certFile); err != nil {
return err return err
} }
if err, keyFile = httpd.StringParam("https.server.key"); err != nil { if err, keyFile = mod.StringParam("https.server.key"); err != nil {
return err return err
} else if keyFile, err = fs.Expand(keyFile); err != nil { } else if keyFile, err = fs.Expand(keyFile); err != nil {
return err return err
} }
if !fs.Exists(certFile) || !fs.Exists(keyFile) { if !fs.Exists(certFile) || !fs.Exists(keyFile) {
err, cfg := tls.CertConfigFromModule("https.server", httpd.SessionModule) err, cfg := tls.CertConfigFromModule("https.server", mod.SessionModule)
if err != nil { if err != nil {
return err return err
} }
httpd.Debug("%+v", cfg) mod.Debug("%+v", cfg)
httpd.Info("generating server TLS key to %s", keyFile) mod.Info("generating server TLS key to %s", keyFile)
httpd.Info("generating server TLS certificate to %s", certFile) mod.Info("generating server TLS certificate to %s", certFile)
if err := tls.Generate(cfg, certFile, keyFile); err != nil { if err := tls.Generate(cfg, certFile, keyFile); err != nil {
return err return err
} }
} else { } else {
httpd.Info("loading server TLS key from %s", keyFile) mod.Info("loading server TLS key from %s", keyFile)
httpd.Info("loading server TLS certificate from %s", certFile) mod.Info("loading server TLS certificate from %s", certFile)
} }
httpd.certFile = certFile mod.certFile = certFile
httpd.keyFile = keyFile mod.keyFile = keyFile
return nil return nil
} }
func (httpd *HttpsServer) Start() error { func (mod *HttpsServer) Start() error {
if err := httpd.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return httpd.SetRunning(true, func() { return mod.SetRunning(true, func() {
httpd.Info("starting on https://%s", httpd.server.Addr) mod.Info("starting on https://%s", mod.server.Addr)
if err := httpd.server.ListenAndServeTLS(httpd.certFile, httpd.keyFile); err != nil && err != http.ErrServerClosed { if err := mod.server.ListenAndServeTLS(mod.certFile, mod.keyFile); err != nil && err != http.ErrServerClosed {
panic(err) panic(err)
} }
}) })
} }
func (httpd *HttpsServer) Stop() error { func (mod *HttpsServer) Stop() error {
return httpd.SetRunning(false, func() { return mod.SetRunning(false, func() {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel() defer cancel()
httpd.server.Shutdown(ctx) mod.server.Shutdown(ctx)
}) })
} }

View file

@ -21,106 +21,106 @@ type MacChanger struct {
} }
func NewMacChanger(s *session.Session) *MacChanger { func NewMacChanger(s *session.Session) *MacChanger {
mc := &MacChanger{ mod := &MacChanger{
SessionModule: session.NewSessionModule("mac.changer", s), SessionModule: session.NewSessionModule("mac.changer", s),
} }
mc.AddParam(session.NewStringParameter("mac.changer.iface", mod.AddParam(session.NewStringParameter("mac.changer.iface",
session.ParamIfaceName, session.ParamIfaceName,
"", "",
"Name of the interface to use.")) "Name of the interface to use."))
mc.AddParam(session.NewStringParameter("mac.changer.address", mod.AddParam(session.NewStringParameter("mac.changer.address",
session.ParamRandomMAC, session.ParamRandomMAC,
"[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}", "[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}",
"Hardware address to apply to the interface.")) "Hardware address to apply to the interface."))
mc.AddHandler(session.NewModuleHandler("mac.changer on", "", mod.AddHandler(session.NewModuleHandler("mac.changer on", "",
"Start mac changer module.", "Start mac changer module.",
func(args []string) error { func(args []string) error {
return mc.Start() return mod.Start()
})) }))
mc.AddHandler(session.NewModuleHandler("mac.changer off", "", mod.AddHandler(session.NewModuleHandler("mac.changer off", "",
"Stop mac changer module and restore original mac address.", "Stop mac changer module and restore original mac address.",
func(args []string) error { func(args []string) error {
return mc.Stop() return mod.Stop()
})) }))
return mc return mod
} }
func (mc *MacChanger) Name() string { func (mod *MacChanger) Name() string {
return "mac.changer" return "mac.changer"
} }
func (mc *MacChanger) Description() string { func (mod *MacChanger) Description() string {
return "Change active interface mac address." return "Change active interface mac address."
} }
func (mc *MacChanger) Author() string { func (mod *MacChanger) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (mc *MacChanger) Configure() (err error) { func (mod *MacChanger) Configure() (err error) {
var changeTo string var changeTo string
if err, mc.iface = mc.StringParam("mac.changer.iface"); err != nil { if err, mod.iface = mod.StringParam("mac.changer.iface"); err != nil {
return err return err
} else if err, changeTo = mc.StringParam("mac.changer.address"); err != nil { } else if err, changeTo = mod.StringParam("mac.changer.address"); err != nil {
return err return err
} }
changeTo = network.NormalizeMac(changeTo) changeTo = network.NormalizeMac(changeTo)
if mc.fakeMac, err = net.ParseMAC(changeTo); err != nil { if mod.fakeMac, err = net.ParseMAC(changeTo); err != nil {
return err return err
} }
mc.originalMac = mc.Session.Interface.HW mod.originalMac = mod.Session.Interface.HW
return nil return nil
} }
func (mc *MacChanger) setMac(mac net.HardwareAddr) error { func (mod *MacChanger) setMac(mac net.HardwareAddr) error {
var args []string var args []string
os := runtime.GOOS os := runtime.GOOS
if strings.Contains(os, "bsd") || os == "darwin" { if strings.Contains(os, "bsd") || os == "darwin" {
args = []string{mc.iface, "ether", mac.String()} args = []string{mod.iface, "ether", mac.String()}
} else if os == "linux" || os == "android" { } else if os == "linux" || os == "android" {
args = []string{mc.iface, "hw", "ether", mac.String()} args = []string{mod.iface, "hw", "ether", mac.String()}
} else { } else {
return fmt.Errorf("OS %s is not supported by mac.changer module.", os) return fmt.Errorf("OS %s is not supported by mac.changer module.", os)
} }
_, err := core.Exec("ifconfig", args) _, err := core.Exec("ifconfig", args)
if err == nil { if err == nil {
mc.Session.Interface.HW = mac mod.Session.Interface.HW = mac
} }
return err return err
} }
func (mc *MacChanger) Start() error { func (mod *MacChanger) Start() error {
if mc.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err := mc.Configure(); err != nil { } else if err := mod.Configure(); err != nil {
return err return err
} else if err := mc.setMac(mc.fakeMac); err != nil { } else if err := mod.setMac(mod.fakeMac); err != nil {
return err return err
} }
return mc.SetRunning(true, func() { return mod.SetRunning(true, func() {
mc.Info("interface mac address set to %s", tui.Bold(mc.fakeMac.String())) mod.Info("interface mac address set to %s", tui.Bold(mod.fakeMac.String()))
}) })
} }
func (mc *MacChanger) Stop() error { func (mod *MacChanger) Stop() error {
return mc.SetRunning(false, func() { return mod.SetRunning(false, func() {
if err := mc.setMac(mc.originalMac); err == nil { if err := mod.setMac(mod.originalMac); err == nil {
mc.Info("interface mac address restored to %s", tui.Bold(mc.originalMac.String())) mod.Info("interface mac address restored to %s", tui.Bold(mod.originalMac.String()))
} else { } else {
mc.Error("error while restoring mac address: %s", err) mod.Error("error while restoring mac address: %s", err)
} }
}) })
} }

View file

@ -7,7 +7,7 @@ import (
"github.com/bettercap/bettercap/modules/ble" "github.com/bettercap/bettercap/modules/ble"
"github.com/bettercap/bettercap/modules/caplets" "github.com/bettercap/bettercap/modules/caplets"
"github.com/bettercap/bettercap/modules/dhcp6_spoof" "github.com/bettercap/bettercap/modules/dhcp6_spoof"
"github.com/bettercap/bettercap/modules/discovery" "github.com/bettercap/bettercap/modules/net_recon"
"github.com/bettercap/bettercap/modules/dns_spoof" "github.com/bettercap/bettercap/modules/dns_spoof"
"github.com/bettercap/bettercap/modules/events_stream" "github.com/bettercap/bettercap/modules/events_stream"
"github.com/bettercap/bettercap/modules/gps" "github.com/bettercap/bettercap/modules/gps"
@ -19,7 +19,7 @@ import (
"github.com/bettercap/bettercap/modules/mysql_server" "github.com/bettercap/bettercap/modules/mysql_server"
"github.com/bettercap/bettercap/modules/net_sniff" "github.com/bettercap/bettercap/modules/net_sniff"
"github.com/bettercap/bettercap/modules/packet_proxy" "github.com/bettercap/bettercap/modules/packet_proxy"
"github.com/bettercap/bettercap/modules/prober" "github.com/bettercap/bettercap/modules/net_probe"
"github.com/bettercap/bettercap/modules/syn_scan" "github.com/bettercap/bettercap/modules/syn_scan"
"github.com/bettercap/bettercap/modules/tcp_proxy" "github.com/bettercap/bettercap/modules/tcp_proxy"
"github.com/bettercap/bettercap/modules/ticker" "github.com/bettercap/bettercap/modules/ticker"
@ -37,7 +37,7 @@ func LoadModules(sess *session.Session) {
sess.Register(ble.NewBLERecon(sess)) sess.Register(ble.NewBLERecon(sess))
sess.Register(caplets.NewCapletsModule(sess)) sess.Register(caplets.NewCapletsModule(sess))
sess.Register(dhcp6_spoof.NewDHCP6Spoofer(sess)) sess.Register(dhcp6_spoof.NewDHCP6Spoofer(sess))
sess.Register(discovery.NewDiscovery(sess)) sess.Register(net_recon.NewDiscovery(sess))
sess.Register(dns_spoof.NewDNSSpoofer(sess)) sess.Register(dns_spoof.NewDNSSpoofer(sess))
sess.Register(events_stream.NewEventsStream(sess)) sess.Register(events_stream.NewEventsStream(sess))
sess.Register(gps.NewGPS(sess)) sess.Register(gps.NewGPS(sess))
@ -49,7 +49,7 @@ func LoadModules(sess *session.Session) {
sess.Register(mysql_server.NewMySQLServer(sess)) sess.Register(mysql_server.NewMySQLServer(sess))
sess.Register(net_sniff.NewSniffer(sess)) sess.Register(net_sniff.NewSniffer(sess))
sess.Register(packet_proxy.NewPacketProxy(sess)) sess.Register(packet_proxy.NewPacketProxy(sess))
sess.Register(prober.NewProber(sess)) sess.Register(net_probe.NewProber(sess))
sess.Register(syn_scan.NewSynScanner(sess)) sess.Register(syn_scan.NewSynScanner(sess))
sess.Register(tcp_proxy.NewTcpProxy(sess)) sess.Register(tcp_proxy.NewTcpProxy(sess))
sess.Register(ticker.NewTicker(sess)) sess.Register(ticker.NewTicker(sess))

View file

@ -23,90 +23,89 @@ type MySQLServer struct {
} }
func NewMySQLServer(s *session.Session) *MySQLServer { func NewMySQLServer(s *session.Session) *MySQLServer {
mod := &MySQLServer{
mysql := &MySQLServer{
SessionModule: session.NewSessionModule("mysql.server", s), SessionModule: session.NewSessionModule("mysql.server", s),
} }
mysql.AddParam(session.NewStringParameter("mysql.server.infile", mod.AddParam(session.NewStringParameter("mysql.server.infile",
"/etc/passwd", "/etc/passwd",
"", "",
"File you want to read. UNC paths are also supported.")) "File you want to read. UNC paths are also supported."))
mysql.AddParam(session.NewStringParameter("mysql.server.outfile", mod.AddParam(session.NewStringParameter("mysql.server.outfile",
"", "",
"", "",
"If filled, the INFILE buffer will be saved to this path instead of being logged.")) "If filled, the INFILE buffer will be saved to this path instead of being logged."))
mysql.AddParam(session.NewStringParameter("mysql.server.address", mod.AddParam(session.NewStringParameter("mysql.server.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address to bind the mysql server to.")) "Address to bind the mysql server to."))
mysql.AddParam(session.NewIntParameter("mysql.server.port", mod.AddParam(session.NewIntParameter("mysql.server.port",
"3306", "3306",
"Port to bind the mysql server to.")) "Port to bind the mysql server to."))
mysql.AddHandler(session.NewModuleHandler("mysql.server on", "", mod.AddHandler(session.NewModuleHandler("mysql.server on", "",
"Start mysql server.", "Start mysql server.",
func(args []string) error { func(args []string) error {
return mysql.Start() return mod.Start()
})) }))
mysql.AddHandler(session.NewModuleHandler("mysql.server off", "", mod.AddHandler(session.NewModuleHandler("mysql.server off", "",
"Stop mysql server.", "Stop mysql server.",
func(args []string) error { func(args []string) error {
return mysql.Stop() return mod.Stop()
})) }))
return mysql return mod
} }
func (mysql *MySQLServer) Name() string { func (mod *MySQLServer) Name() string {
return "mysql.server" return "mysql.server"
} }
func (mysql *MySQLServer) Description() string { func (mod *MySQLServer) Description() string {
return "A simple Rogue MySQL server, to be used to exploit LOCAL INFILE and read arbitrary files from the client." return "A simple Rogue MySQL server, to be used to exploit LOCAL INFILE and read arbitrary files from the client."
} }
func (mysql *MySQLServer) Author() string { func (mod *MySQLServer) Author() string {
return "Bernardo Rodrigues (https://twitter.com/bernardomr)" return "Bernardo Rodrigues (https://twitter.com/bernardomr)"
} }
func (mysql *MySQLServer) Configure() error { func (mod *MySQLServer) Configure() error {
var err error var err error
var address string var address string
var port int var port int
if mysql.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, mysql.infile = mysql.StringParam("mysql.server.infile"); err != nil { } else if err, mod.infile = mod.StringParam("mysql.server.infile"); err != nil {
return err return err
} else if err, mysql.outfile = mysql.StringParam("mysql.server.outfile"); err != nil { } else if err, mod.outfile = mod.StringParam("mysql.server.outfile"); err != nil {
return err return err
} else if err, address = mysql.StringParam("mysql.server.address"); err != nil { } else if err, address = mod.StringParam("mysql.server.address"); err != nil {
return err return err
} else if err, port = mysql.IntParam("mysql.server.port"); err != nil { } else if err, port = mod.IntParam("mysql.server.port"); err != nil {
return err return err
} else if mysql.address, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", address, port)); err != nil { } else if mod.address, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", address, port)); err != nil {
return err return err
} else if mysql.listener, err = net.ListenTCP("tcp", mysql.address); err != nil { } else if mod.listener, err = net.ListenTCP("tcp", mod.address); err != nil {
return err return err
} }
return nil return nil
} }
func (mysql *MySQLServer) Start() error { func (mod *MySQLServer) Start() error {
if err := mysql.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return mysql.SetRunning(true, func() { return mod.SetRunning(true, func() {
mysql.Info("server starting on address %s", mysql.address) mod.Info("server starting on address %s", mod.address)
for mysql.Running() { for mod.Running() {
if conn, err := mysql.listener.AcceptTCP(); err != nil { if conn, err := mod.listener.AcceptTCP(); err != nil {
mysql.Warning("error while accepting tcp connection: %s", err) mod.Warning("error while accepting tcp connection: %s", err)
continue continue
} else { } else {
defer conn.Close() defer conn.Close()
@ -117,13 +116,13 @@ func (mysql *MySQLServer) Start() error {
reader := bufio.NewReader(conn) reader := bufio.NewReader(conn)
read := 0 read := 0
mysql.Info("connection from %s", clientAddress) mod.Info("connection from %s", clientAddress)
if _, err := conn.Write(packets.MySQLGreeting); err != nil { if _, err := conn.Write(packets.MySQLGreeting); err != nil {
mysql.Warning("error while writing server greeting: %s", err) mod.Warning("error while writing server greeting: %s", err)
continue continue
} else if read, err = reader.Read(readBuffer); err != nil { } else if read, err = reader.Read(readBuffer); err != nil {
mysql.Warning("error while reading client message: %s", err) mod.Warning("error while reading client message: %s", err)
continue continue
} }
@ -134,38 +133,38 @@ func (mysql *MySQLServer) Start() error {
loadData := string(capabilities[8]) loadData := string(capabilities[8])
username := string(bytes.Split(readBuffer[36:], []byte{0})[0]) username := string(bytes.Split(readBuffer[36:], []byte{0})[0])
mysql.Info("can use LOAD DATA LOCAL: %s", loadData) mod.Info("can use LOAD DATA LOCAL: %s", loadData)
mysql.Info("login request username: %s", tui.Bold(username)) mod.Info("login request username: %s", tui.Bold(username))
if _, err := conn.Write(packets.MySQLFirstResponseOK); err != nil { if _, err := conn.Write(packets.MySQLFirstResponseOK); err != nil {
mysql.Warning("error while writing server first response ok: %s", err) mod.Warning("error while writing server first response ok: %s", err)
continue continue
} else if _, err := reader.Read(readBuffer); err != nil { } else if _, err := reader.Read(readBuffer); err != nil {
mysql.Warning("error while reading client message: %s", err) mod.Warning("error while reading client message: %s", err)
continue continue
} else if _, err := conn.Write(packets.MySQLGetFile(mysql.infile)); err != nil { } else if _, err := conn.Write(packets.MySQLGetFile(mod.infile)); err != nil {
mysql.Warning("error while writing server get file request: %s", err) mod.Warning("error while writing server get file request: %s", err)
continue continue
} else if read, err = reader.Read(readBuffer); err != nil { } else if read, err = reader.Read(readBuffer); err != nil {
mysql.Warning("error while readind buffer: %s", err) mod.Warning("error while readind buffer: %s", err)
continue continue
} }
if strings.HasPrefix(mysql.infile, "\\") { if strings.HasPrefix(mod.infile, "\\") {
mysql.Info("NTLM from '%s' relayed to %s", clientAddress, mysql.infile) mod.Info("NTLM from '%s' relayed to %s", clientAddress, mod.infile)
} else if fileSize := read - 9; fileSize < 4 { } else if fileSize := read - 9; fileSize < 4 {
mysql.Warning("unpexpected buffer size %d", read) mod.Warning("unpexpected buffer size %d", read)
} else { } else {
mysql.Info("read file ( %s ) is %d bytes", mysql.infile, fileSize) mod.Info("read file ( %s ) is %d bytes", mod.infile, fileSize)
fileData := readBuffer[4 : read-4] fileData := readBuffer[4 : read-4]
if mysql.outfile == "" { if mod.outfile == "" {
mysql.Info("\n%s", string(fileData)) mod.Info("\n%s", string(fileData))
} else { } else {
mysql.Info("saving to %s ...", mysql.outfile) mod.Info("saving to %s ...", mod.outfile)
if err := ioutil.WriteFile(mysql.outfile, fileData, 0755); err != nil { if err := ioutil.WriteFile(mod.outfile, fileData, 0755); err != nil {
mysql.Warning("error while saving the file: %s", err) mod.Warning("error while saving the file: %s", err)
} }
} }
} }
@ -176,8 +175,8 @@ func (mysql *MySQLServer) Start() error {
}) })
} }
func (mysql *MySQLServer) Stop() error { func (mod *MySQLServer) Stop() error {
return mysql.SetRunning(false, func() { return mod.SetRunning(false, func() {
defer mysql.listener.Close() defer mod.listener.Close()
}) })
} }

View file

@ -0,0 +1,156 @@
package net_probe
import (
"sync"
"time"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/session"
"github.com/malfunkt/iprange"
)
type Probes struct {
NBNS bool
MDNS bool
UPNP bool
WSD bool
}
type Prober struct {
session.SessionModule
throttle int
probes Probes
waitGroup *sync.WaitGroup
}
func NewProber(s *session.Session) *Prober {
mod := &Prober{
SessionModule: session.NewSessionModule("net.probe", s),
waitGroup: &sync.WaitGroup{},
}
mod.AddParam(session.NewBoolParameter("net.probe.nbns",
"true",
"Enable NetBIOS name service discovery probes."))
mod.AddParam(session.NewBoolParameter("net.probe.mdns",
"true",
"Enable mDNS discovery probes."))
mod.AddParam(session.NewBoolParameter("net.probe.upnp",
"true",
"Enable UPNP discovery probes."))
mod.AddParam(session.NewBoolParameter("net.probe.wsd",
"true",
"Enable WSD discovery probes."))
mod.AddParam(session.NewIntParameter("net.probe.throttle",
"10",
"If greater than 0, probe packets will be throttled by this value in milliseconds."))
mod.AddHandler(session.NewModuleHandler("net.probe on", "",
"Start network hosts probing in background.",
func(args []string) error {
return mod.Start()
}))
mod.AddHandler(session.NewModuleHandler("net.probe off", "",
"Stop network hosts probing in background.",
func(args []string) error {
return mod.Stop()
}))
return mod
}
func (mod Prober) Name() string {
return "net.probe"
}
func (mod Prober) Description() string {
return "Keep probing for new hosts on the network by sending dummy UDP packets to every possible IP on the subnet."
}
func (mod Prober) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>"
}
func (mod *Prober) Configure() error {
var err error
if err, mod.throttle = mod.IntParam("net.probe.throttle"); err != nil {
return err
} else if err, mod.probes.NBNS = mod.BoolParam("net.probe.nbns"); err != nil {
return err
} else if err, mod.probes.MDNS = mod.BoolParam("net.probe.mdns"); err != nil {
return err
} else if err, mod.probes.UPNP = mod.BoolParam("net.probe.upnp"); err != nil {
return err
} else if err, mod.probes.WSD = mod.BoolParam("net.probe.wsd"); err != nil {
return err
} else {
mod.Debug("Throttling packets of %d ms.", mod.throttle)
}
return nil
}
func (mod *Prober) Start() error {
if err := mod.Configure(); err != nil {
return err
}
return mod.SetRunning(true, func() {
mod.waitGroup.Add(1)
defer mod.waitGroup.Done()
if mod.Session.Interface.IpAddress == network.MonitorModeAddress {
mod.Info("Interface is in monitor mode, skipping net.probe")
return
}
list, err := iprange.Parse(mod.Session.Interface.CIDR())
if err != nil {
mod.Fatal("%s", err)
}
fromIP := mod.Session.Interface.IP
fromHW := mod.Session.Interface.HW
addresses := list.Expand()
throttle := time.Duration(mod.throttle) * time.Millisecond
for mod.Running() {
if mod.probes.MDNS {
mod.sendProbeMDNS(fromIP, fromHW)
}
if mod.probes.UPNP {
mod.sendProbeUPNP(fromIP, fromHW)
}
if mod.probes.WSD {
mod.sendProbeWSD(fromIP, fromHW)
}
for _, ip := range addresses {
if !mod.Running() {
return
} else if mod.Session.Skip(ip) {
mod.Debug("skipping address %s from probing.", ip)
continue
} else if mod.probes.NBNS {
mod.sendProbeNBNS(fromIP, fromHW, ip)
}
time.Sleep(throttle)
}
time.Sleep(5 * time.Second)
}
})
}
func (mod *Prober) Stop() error {
return mod.SetRunning(false, func() {
mod.waitGroup.Wait()
})
}

View file

@ -0,0 +1,19 @@
package net_probe
import (
"net"
"github.com/bettercap/bettercap/packets"
)
func (mod *Prober) sendProbeMDNS(from net.IP, from_hw net.HardwareAddr) {
err, raw := packets.NewMDNSProbe(from, from_hw)
if err != nil {
mod.Error("error while sending mdns probe: %v", err)
return
} else if err := mod.Session.Queue.Send(raw); err != nil {
mod.Error("error sending mdns packet: %s", err)
} else {
mod.Debug("sent %d bytes of MDNS probe", len(raw))
}
}

View file

@ -1,4 +1,4 @@
package prober package net_probe
import ( import (
"fmt" "fmt"
@ -7,18 +7,18 @@ import (
"github.com/bettercap/bettercap/packets" "github.com/bettercap/bettercap/packets"
) )
func (p *Prober) sendProbeNBNS(from net.IP, from_hw net.HardwareAddr, ip net.IP) { func (mod *Prober) sendProbeNBNS(from net.IP, from_hw net.HardwareAddr, ip net.IP) {
name := fmt.Sprintf("%s:%d", ip, packets.NBNSPort) name := fmt.Sprintf("%s:%d", ip, packets.NBNSPort)
if addr, err := net.ResolveUDPAddr("udp", name); err != nil { if addr, err := net.ResolveUDPAddr("udp", name); err != nil {
p.Debug("could not resolve %s.", name) mod.Debug("could not resolve %s.", name)
} else if con, err := net.DialUDP("udp", nil, addr); err != nil { } else if con, err := net.DialUDP("udp", nil, addr); err != nil {
p.Debug("could not dial %s.", name) mod.Debug("could not dial %s.", name)
} else { } else {
defer con.Close() defer con.Close()
if wrote, _ := con.Write(packets.NBNSRequest); wrote > 0 { if wrote, _ := con.Write(packets.NBNSRequest); wrote > 0 {
p.Session.Queue.TrackSent(uint64(wrote)) mod.Session.Queue.TrackSent(uint64(wrote))
} else { } else {
p.Session.Queue.TrackError() mod.Session.Queue.TrackError()
} }
} }
} }

View file

@ -1,4 +1,4 @@
package prober package net_probe
import ( import (
"fmt" "fmt"
@ -7,18 +7,18 @@ import (
"github.com/bettercap/bettercap/packets" "github.com/bettercap/bettercap/packets"
) )
func (p *Prober) sendProbeUPNP(from net.IP, from_hw net.HardwareAddr) { func (mod *Prober) sendProbeUPNP(from net.IP, from_hw net.HardwareAddr) {
name := fmt.Sprintf("%s:%d", packets.UPNPDestIP, packets.UPNPPort) name := fmt.Sprintf("%s:%d", packets.UPNPDestIP, packets.UPNPPort)
if addr, err := net.ResolveUDPAddr("udp", name); err != nil { if addr, err := net.ResolveUDPAddr("udp", name); err != nil {
p.Debug("could not resolve %s.", name) mod.Debug("could not resolve %s.", name)
} else if con, err := net.DialUDP("udp", nil, addr); err != nil { } else if con, err := net.DialUDP("udp", nil, addr); err != nil {
p.Debug("could not dial %s.", name) mod.Debug("could not dial %s.", name)
} else { } else {
defer con.Close() defer con.Close()
if wrote, _ := con.Write(packets.UPNPDiscoveryPayload); wrote > 0 { if wrote, _ := con.Write(packets.UPNPDiscoveryPayload); wrote > 0 {
p.Session.Queue.TrackSent(uint64(wrote)) mod.Session.Queue.TrackSent(uint64(wrote))
} else { } else {
p.Session.Queue.TrackError() mod.Session.Queue.TrackError()
} }
} }

View file

@ -1,4 +1,4 @@
package prober package net_probe
import ( import (
"fmt" "fmt"
@ -7,18 +7,18 @@ import (
"github.com/bettercap/bettercap/packets" "github.com/bettercap/bettercap/packets"
) )
func (p *Prober) sendProbeWSD(from net.IP, from_hw net.HardwareAddr) { func (mod *Prober) sendProbeWSD(from net.IP, from_hw net.HardwareAddr) {
name := fmt.Sprintf("%s:%d", packets.WSDDestIP, packets.WSDPort) name := fmt.Sprintf("%s:%d", packets.WSDDestIP, packets.WSDPort)
if addr, err := net.ResolveUDPAddr("udp", name); err != nil { if addr, err := net.ResolveUDPAddr("udp", name); err != nil {
p.Debug("could not resolve %s.", name) mod.Debug("could not resolve %s.", name)
} else if con, err := net.DialUDP("udp", nil, addr); err != nil { } else if con, err := net.DialUDP("udp", nil, addr); err != nil {
p.Debug("could not dial %s.", name) mod.Debug("could not dial %s.", name)
} else { } else {
defer con.Close() defer con.Close()
if wrote, _ := con.Write(packets.WSDDiscoveryPayload); wrote > 0 { if wrote, _ := con.Write(packets.WSDDiscoveryPayload); wrote > 0 {
p.Session.Queue.TrackSent(uint64(wrote)) mod.Session.Queue.TrackSent(uint64(wrote))
} else { } else {
p.Session.Queue.TrackError() mod.Session.Queue.TrackError()
} }
} }

View file

@ -1,4 +1,4 @@
package discovery package net_recon
import ( import (
"github.com/bettercap/bettercap/modules/utils" "github.com/bettercap/bettercap/modules/utils"
@ -14,105 +14,105 @@ type Discovery struct {
} }
func NewDiscovery(s *session.Session) *Discovery { func NewDiscovery(s *session.Session) *Discovery {
d := &Discovery{ mod := &Discovery{
SessionModule: session.NewSessionModule("net.recon", s), SessionModule: session.NewSessionModule("net.recon", s),
} }
d.AddHandler(session.NewModuleHandler("net.recon on", "", mod.AddHandler(session.NewModuleHandler("net.recon on", "",
"Start network hosts discovery.", "Start network hosts discovery.",
func(args []string) error { func(args []string) error {
return d.Start() return mod.Start()
})) }))
d.AddHandler(session.NewModuleHandler("net.recon off", "", mod.AddHandler(session.NewModuleHandler("net.recon off", "",
"Stop network hosts discovery.", "Stop network hosts discovery.",
func(args []string) error { func(args []string) error {
return d.Stop() return mod.Stop()
})) }))
d.AddParam(session.NewBoolParameter("net.show.meta", mod.AddParam(session.NewBoolParameter("net.show.meta",
"false", "false",
"If true, the net.show command will show all metadata collected about each endpoint.")) "If true, the net.show command will show all metadata collected about each endpoint."))
d.AddHandler(session.NewModuleHandler("net.show", "", mod.AddHandler(session.NewModuleHandler("net.show", "",
"Show cache hosts list (default sorting by ip).", "Show cache hosts list (default sorting by ip).",
func(args []string) error { func(args []string) error {
return d.Show("") return mod.Show("")
})) }))
d.AddHandler(session.NewModuleHandler("net.show ADDRESS1, ADDRESS2", `net.show (.+)`, mod.AddHandler(session.NewModuleHandler("net.show ADDRESS1, ADDRESS2", `net.show (.+)`,
"Show information about a specific list of addresses (by IP or MAC).", "Show information about a specific list of addresses (by IP or MAC).",
func(args []string) error { func(args []string) error {
return d.Show(args[0]) return mod.Show(args[0])
})) }))
d.AddHandler(session.NewModuleHandler("net.show.meta ADDRESS1, ADDRESS2", `net\.show\.meta (.+)`, mod.AddHandler(session.NewModuleHandler("net.show.meta ADDRESS1, ADDRESS2", `net\.show\.meta (.+)`,
"Show meta information about a specific list of addresses (by IP or MAC).", "Show meta information about a specific list of addresses (by IP or MAC).",
func(args []string) error { func(args []string) error {
return d.showMeta(args[0]) return mod.showMeta(args[0])
})) }))
d.selector = utils.ViewSelectorFor(&d.SessionModule, "net.show", []string{"ip", "mac", "seen", "sent", "rcvd"}, mod.selector = utils.ViewSelectorFor(&mod.SessionModule, "net.show", []string{"ip", "mac", "seen", "sent", "rcvd"},
"ip asc") "ip asc")
return d return mod
} }
func (d Discovery) Name() string { func (mod Discovery) Name() string {
return "net.recon" return "net.recon"
} }
func (d Discovery) Description() string { func (mod Discovery) Description() string {
return "Read periodically the ARP cache in order to monitor for new hosts on the network." return "Read periodically the ARP cache in order to monitor for new hosts on the network."
} }
func (d Discovery) Author() string { func (mod Discovery) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (d *Discovery) runDiff(cache network.ArpTable) { func (mod *Discovery) runDiff(cache network.ArpTable) {
// check for endpoints who disappeared // check for endpoints who disappeared
var rem network.ArpTable = make(network.ArpTable) var rem network.ArpTable = make(network.ArpTable)
d.Session.Lan.EachHost(func(mac string, e *network.Endpoint) { mod.Session.Lan.EachHost(func(mac string, e *network.Endpoint) {
if _, found := cache[mac]; !found { if _, found := cache[mac]; !found {
rem[mac] = e.IpAddress rem[mac] = e.IpAddress
} }
}) })
for mac, ip := range rem { for mac, ip := range rem {
d.Session.Lan.Remove(ip, mac) mod.Session.Lan.Remove(ip, mac)
} }
// now check for new friends ^_^ // now check for new friends ^_^
for ip, mac := range cache { for ip, mac := range cache {
d.Session.Lan.AddIfNew(ip, mac) mod.Session.Lan.AddIfNew(ip, mac)
} }
} }
func (d *Discovery) Configure() error { func (mod *Discovery) Configure() error {
return nil return nil
} }
func (d *Discovery) Start() error { func (mod *Discovery) Start() error {
if err := d.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return d.SetRunning(true, func() { return mod.SetRunning(true, func() {
every := time.Duration(1) * time.Second every := time.Duration(1) * time.Second
iface := d.Session.Interface.Name() iface := mod.Session.Interface.Name()
for d.Running() { for mod.Running() {
if table, err := network.ArpUpdate(iface); err != nil { if table, err := network.ArpUpdate(iface); err != nil {
d.Error("%s", err) mod.Error("%s", err)
} else { } else {
d.runDiff(table) mod.runDiff(table)
} }
time.Sleep(every) time.Sleep(every)
} }
}) })
} }
func (d *Discovery) Stop() error { func (mod *Discovery) Stop() error {
return d.SetRunning(false, nil) return mod.SetRunning(false, nil)
} }

View file

@ -1,4 +1,4 @@
package discovery package net_recon
import ( import (
"fmt" "fmt"
@ -32,13 +32,13 @@ func (p ProtoPairList) Len() int { return len(p) }
func (p ProtoPairList) Less(i, j int) bool { return p[i].Hits < p[j].Hits } func (p ProtoPairList) Less(i, j int) bool { return p[i].Hits < p[j].Hits }
func (p ProtoPairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p ProtoPairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string { func (mod *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string {
sinceStarted := time.Since(d.Session.StartedAt) sinceStarted := time.Since(mod.Session.StartedAt)
sinceFirstSeen := time.Since(e.FirstSeen) sinceFirstSeen := time.Since(e.FirstSeen)
addr := e.IpAddress addr := e.IpAddress
mac := e.HwAddress mac := e.HwAddress
if d.Session.Lan.WasMissed(e.HwAddress) { if mod.Session.Lan.WasMissed(e.HwAddress) {
// if endpoint was not found in ARP at least once // if endpoint was not found in ARP at least once
addr = tui.Dim(addr) addr = tui.Dim(addr)
mac = tui.Dim(mac) mac = tui.Dim(mac)
@ -49,9 +49,9 @@ func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string {
} }
name := "" name := ""
if e == d.Session.Interface { if e == mod.Session.Interface {
name = e.Name() name = e.Name()
} else if e == d.Session.Gateway { } else if e == mod.Session.Gateway {
name = "gateway" name = "gateway"
} else if e.Alias != "" { } else if e.Alias != "" {
name = tui.Green(e.Alias) name = tui.Green(e.Alias)
@ -61,7 +61,7 @@ func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string {
var traffic *packets.Traffic var traffic *packets.Traffic
var found bool var found bool
if traffic, found = d.Session.Queue.Traffic[e.IpAddress]; !found { if traffic, found = mod.Session.Queue.Traffic[e.IpAddress]; !found {
traffic = &packets.Traffic{} traffic = &packets.Traffic{}
} }
@ -111,40 +111,40 @@ func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string {
return rows return rows
} }
func (d *Discovery) doFilter(target *network.Endpoint) bool { func (mod *Discovery) doFilter(target *network.Endpoint) bool {
if d.selector.Expression == nil { if mod.selector.Expression == nil {
return true return true
} }
return d.selector.Expression.MatchString(target.IpAddress) || return mod.selector.Expression.MatchString(target.IpAddress) ||
d.selector.Expression.MatchString(target.Ip6Address) || mod.selector.Expression.MatchString(target.Ip6Address) ||
d.selector.Expression.MatchString(target.HwAddress) || mod.selector.Expression.MatchString(target.HwAddress) ||
d.selector.Expression.MatchString(target.Hostname) || mod.selector.Expression.MatchString(target.Hostname) ||
d.selector.Expression.MatchString(target.Alias) || mod.selector.Expression.MatchString(target.Alias) ||
d.selector.Expression.MatchString(target.Vendor) mod.selector.Expression.MatchString(target.Vendor)
} }
func (d *Discovery) doSelection(arg string) (err error, targets []*network.Endpoint) { func (mod *Discovery) doSelection(arg string) (err error, targets []*network.Endpoint) {
if err = d.selector.Update(); err != nil { if err = mod.selector.Update(); err != nil {
return return
} }
if arg != "" { if arg != "" {
if targets, err = network.ParseEndpoints(arg, d.Session.Lan); err != nil { if targets, err = network.ParseEndpoints(arg, mod.Session.Lan); err != nil {
return return
} }
} else { } else {
targets = d.Session.Lan.List() targets = mod.Session.Lan.List()
} }
filtered := []*network.Endpoint{} filtered := []*network.Endpoint{}
for _, target := range targets { for _, target := range targets {
if d.doFilter(target) { if mod.doFilter(target) {
filtered = append(filtered, target) filtered = append(filtered, target)
} }
} }
targets = filtered targets = filtered
switch d.selector.SortField { switch mod.selector.SortField {
case "ip": case "ip":
sort.Sort(ByIpSorter(targets)) sort.Sort(ByIpSorter(targets))
case "mac": case "mac":
@ -160,7 +160,7 @@ func (d *Discovery) doSelection(arg string) (err error, targets []*network.Endpo
} }
// default is asc // default is asc
if d.selector.Sort == "desc" { if mod.selector.Sort == "desc" {
// from https://github.com/golang/go/wiki/SliceTricks // from https://github.com/golang/go/wiki/SliceTricks
for i := len(targets)/2 - 1; i >= 0; i-- { for i := len(targets)/2 - 1; i >= 0; i-- {
opp := len(targets) - 1 - i opp := len(targets) - 1 - i
@ -168,8 +168,8 @@ func (d *Discovery) doSelection(arg string) (err error, targets []*network.Endpo
} }
} }
if d.selector.Limit > 0 { if mod.selector.Limit > 0 {
limit := d.selector.Limit limit := mod.selector.Limit
max := len(targets) max := len(targets)
if limit > max { if limit > max {
limit = max limit = max
@ -180,61 +180,61 @@ func (d *Discovery) doSelection(arg string) (err error, targets []*network.Endpo
return return
} }
func (d *Discovery) colNames(hasMeta bool) []string { func (mod *Discovery) colNames(hasMeta bool) []string {
colNames := []string{"IP", "MAC", "Name", "Vendor", "Sent", "Recvd", "Seen"} colNames := []string{"IP", "MAC", "Name", "Vendor", "Sent", "Recvd", "Seen"}
if hasMeta { if hasMeta {
colNames = append(colNames, "Meta") colNames = append(colNames, "Meta")
} }
switch d.selector.SortField { switch mod.selector.SortField {
case "mac": case "mac":
colNames[1] += " " + d.selector.SortSymbol colNames[1] += " " + mod.selector.SortSymbol
case "sent": case "sent":
colNames[4] += " " + d.selector.SortSymbol colNames[4] += " " + mod.selector.SortSymbol
case "rcvd": case "rcvd":
colNames[5] += " " + d.selector.SortSymbol colNames[5] += " " + mod.selector.SortSymbol
case "seen": case "seen":
colNames[6] += " " + d.selector.SortSymbol colNames[6] += " " + mod.selector.SortSymbol
case "ip": case "ip":
colNames[0] += " " + d.selector.SortSymbol colNames[0] += " " + mod.selector.SortSymbol
} }
return colNames return colNames
} }
func (d *Discovery) showStatusBar() { func (mod *Discovery) showStatusBar() {
d.Session.Queue.Stats.RLock() mod.Session.Queue.Stats.RLock()
defer d.Session.Queue.Stats.RUnlock() defer mod.Session.Queue.Stats.RUnlock()
parts := []string{ parts := []string{
fmt.Sprintf("%s %s", tui.Red("↑"), humanize.Bytes(d.Session.Queue.Stats.Sent)), fmt.Sprintf("%s %s", tui.Red("↑"), humanize.Bytes(mod.Session.Queue.Stats.Sent)),
fmt.Sprintf("%s %s", tui.Green("↓"), humanize.Bytes(d.Session.Queue.Stats.Received)), fmt.Sprintf("%s %s", tui.Green("↓"), humanize.Bytes(mod.Session.Queue.Stats.Received)),
fmt.Sprintf("%d pkts", d.Session.Queue.Stats.PktReceived), fmt.Sprintf("%d pkts", mod.Session.Queue.Stats.PktReceived),
} }
if nErrors := d.Session.Queue.Stats.Errors; nErrors > 0 { if nErrors := mod.Session.Queue.Stats.Errors; nErrors > 0 {
parts = append(parts, fmt.Sprintf("%d errs", nErrors)) parts = append(parts, fmt.Sprintf("%d errs", nErrors))
} }
fmt.Printf("\n%s\n\n", strings.Join(parts, " / ")) fmt.Printf("\n%s\n\n", strings.Join(parts, " / "))
} }
func (d *Discovery) Show(arg string) (err error) { func (mod *Discovery) Show(arg string) (err error) {
var targets []*network.Endpoint var targets []*network.Endpoint
if err, targets = d.doSelection(arg); err != nil { if err, targets = mod.doSelection(arg); err != nil {
return return
} }
pad := 1 pad := 1
if d.Session.Interface.HwAddress == d.Session.Gateway.HwAddress { if mod.Session.Interface.HwAddress == mod.Session.Gateway.HwAddress {
pad = 0 pad = 0
targets = append([]*network.Endpoint{d.Session.Interface}, targets...) targets = append([]*network.Endpoint{mod.Session.Interface}, targets...)
} else { } else {
targets = append([]*network.Endpoint{d.Session.Interface, d.Session.Gateway}, targets...) targets = append([]*network.Endpoint{mod.Session.Interface, mod.Session.Gateway}, targets...)
} }
hasMeta := false hasMeta := false
if err, showMeta := d.BoolParam("net.show.meta"); err != nil { if err, showMeta := mod.BoolParam("net.show.meta"); err != nil {
return err return err
} else if showMeta { } else if showMeta {
for _, t := range targets { for _, t := range targets {
@ -245,12 +245,12 @@ func (d *Discovery) Show(arg string) (err error) {
} }
} }
colNames := d.colNames(hasMeta) colNames := mod.colNames(hasMeta)
padCols := make([]string, len(colNames)) padCols := make([]string, len(colNames))
rows := make([][]string, 0) rows := make([][]string, 0)
for i, t := range targets { for i, t := range targets {
rows = append(rows, d.getRow(t, hasMeta)...) rows = append(rows, mod.getRow(t, hasMeta)...)
if i == pad { if i == pad {
rows = append(rows, padCols) rows = append(rows, padCols)
} }
@ -258,16 +258,16 @@ func (d *Discovery) Show(arg string) (err error) {
tui.Table(os.Stdout, colNames, rows) tui.Table(os.Stdout, colNames, rows)
d.showStatusBar() mod.showStatusBar()
d.Session.Refresh() mod.Session.Refresh()
return nil return nil
} }
func (d *Discovery) showMeta(arg string) (err error) { func (mod *Discovery) showMeta(arg string) (err error) {
var targets []*network.Endpoint var targets []*network.Endpoint
if err, targets = d.doSelection(arg); err != nil { if err, targets = mod.doSelection(arg); err != nil {
return return
} }
@ -303,7 +303,7 @@ func (d *Discovery) showMeta(arg string) (err error) {
} }
if any { if any {
d.Session.Refresh() mod.Session.Refresh()
} }
return nil return nil

View file

@ -1,4 +1,4 @@
package discovery package net_recon
import ( import (
"github.com/bettercap/bettercap/network" "github.com/bettercap/bettercap/network"

View file

@ -24,133 +24,133 @@ type Sniffer struct {
} }
func NewSniffer(s *session.Session) *Sniffer { func NewSniffer(s *session.Session) *Sniffer {
sniff := &Sniffer{ mod := &Sniffer{
SessionModule: session.NewSessionModule("net.sniff", s), SessionModule: session.NewSessionModule("net.sniff", s),
Stats: nil, Stats: nil,
} }
sniff.AddParam(session.NewBoolParameter("net.sniff.verbose", mod.AddParam(session.NewBoolParameter("net.sniff.verbose",
"false", "false",
"If true, every captured and parsed packet will be sent to the events.stream for displaying, otherwise only the ones parsed at the application layer (sni, http, etc).")) "If true, every captured and parsed packet will be sent to the events.stream for displaying, otherwise only the ones parsed at the application layer (sni, http, etc)."))
sniff.AddParam(session.NewBoolParameter("net.sniff.local", mod.AddParam(session.NewBoolParameter("net.sniff.local",
"false", "false",
"If true it will consider packets from/to this computer, otherwise it will skip them.")) "If true it will consider packets from/to this computer, otherwise it will skip them."))
sniff.AddParam(session.NewStringParameter("net.sniff.filter", mod.AddParam(session.NewStringParameter("net.sniff.filter",
"not arp", "not arp",
"", "",
"BPF filter for the sniffer.")) "BPF filter for the sniffer."))
sniff.AddParam(session.NewStringParameter("net.sniff.regexp", mod.AddParam(session.NewStringParameter("net.sniff.regexp",
"", "",
"", "",
"If set, only packets matching this regular expression will be considered.")) "If set, only packets matching this regular expression will be considered."))
sniff.AddParam(session.NewStringParameter("net.sniff.output", mod.AddParam(session.NewStringParameter("net.sniff.output",
"", "",
"", "",
"If set, the sniffer will write captured packets to this file.")) "If set, the sniffer will write captured packets to this file."))
sniff.AddParam(session.NewStringParameter("net.sniff.source", mod.AddParam(session.NewStringParameter("net.sniff.source",
"", "",
"", "",
"If set, the sniffer will read from this pcap file instead of the current interface.")) "If set, the sniffer will read from this pcap file instead of the current interface."))
sniff.AddHandler(session.NewModuleHandler("net.sniff stats", "", mod.AddHandler(session.NewModuleHandler("net.sniff stats", "",
"Print sniffer session configuration and statistics.", "Print sniffer session configuration and statistics.",
func(args []string) error { func(args []string) error {
if sniff.Stats == nil { if mod.Stats == nil {
return fmt.Errorf("No stats yet.") return fmt.Errorf("No stats yet.")
} }
sniff.Ctx.Log(sniff.Session) mod.Ctx.Log(mod.Session)
return sniff.Stats.Print() return mod.Stats.Print()
})) }))
sniff.AddHandler(session.NewModuleHandler("net.sniff on", "", mod.AddHandler(session.NewModuleHandler("net.sniff on", "",
"Start network sniffer in background.", "Start network sniffer in background.",
func(args []string) error { func(args []string) error {
return sniff.Start() return mod.Start()
})) }))
sniff.AddHandler(session.NewModuleHandler("net.sniff off", "", mod.AddHandler(session.NewModuleHandler("net.sniff off", "",
"Stop network sniffer in background.", "Stop network sniffer in background.",
func(args []string) error { func(args []string) error {
return sniff.Stop() return mod.Stop()
})) }))
sniff.AddHandler(session.NewModuleHandler("net.fuzz on", "", mod.AddHandler(session.NewModuleHandler("net.fuzz on", "",
"Enable fuzzing for every sniffed packet containing the sapecified layers.", "Enable fuzzing for every sniffed packet containing the sapecified layers.",
func(args []string) error { func(args []string) error {
return sniff.StartFuzzing() return mod.StartFuzzing()
})) }))
sniff.AddHandler(session.NewModuleHandler("net.fuzz off", "", mod.AddHandler(session.NewModuleHandler("net.fuzz off", "",
"Disable fuzzing", "Disable fuzzing",
func(args []string) error { func(args []string) error {
return sniff.StopFuzzing() return mod.StopFuzzing()
})) }))
sniff.AddParam(session.NewStringParameter("net.fuzz.layers", mod.AddParam(session.NewStringParameter("net.fuzz.layers",
"Payload", "Payload",
"", "",
"Types of layer to fuzz.")) "Types of layer to fuzz."))
sniff.AddParam(session.NewDecimalParameter("net.fuzz.rate", mod.AddParam(session.NewDecimalParameter("net.fuzz.rate",
"1.0", "1.0",
"Rate in the [0.0,1.0] interval of packets to fuzz.")) "Rate in the [0.0,1.0] interval of packets to fuzz."))
sniff.AddParam(session.NewDecimalParameter("net.fuzz.ratio", mod.AddParam(session.NewDecimalParameter("net.fuzz.ratio",
"0.4", "0.4",
"Rate in the [0.0,1.0] interval of bytes to fuzz for each packet.")) "Rate in the [0.0,1.0] interval of bytes to fuzz for each packet."))
sniff.AddParam(session.NewBoolParameter("net.fuzz.silent", mod.AddParam(session.NewBoolParameter("net.fuzz.silent",
"false", "false",
"If true it will not report fuzzed packets.")) "If true it will not report fuzzed packets."))
return sniff return mod
} }
func (s Sniffer) Name() string { func (mod Sniffer) Name() string {
return "net.sniff" return "net.sniff"
} }
func (s Sniffer) Description() string { func (mod Sniffer) Description() string {
return "Sniff packets from the network." return "Sniff packets from the network."
} }
func (s Sniffer) Author() string { func (mod Sniffer) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (s Sniffer) isLocalPacket(packet gopacket.Packet) bool { func (mod Sniffer) isLocalPacket(packet gopacket.Packet) bool {
ipl := packet.Layer(layers.LayerTypeIPv4) ipl := packet.Layer(layers.LayerTypeIPv4)
if ipl != nil { if ipl != nil {
ip, _ := ipl.(*layers.IPv4) ip, _ := ipl.(*layers.IPv4)
if ip.SrcIP.Equal(s.Session.Interface.IP) || ip.DstIP.Equal(s.Session.Interface.IP) { if ip.SrcIP.Equal(mod.Session.Interface.IP) || ip.DstIP.Equal(mod.Session.Interface.IP) {
return true return true
} }
} }
return false return false
} }
func (s *Sniffer) onPacketMatched(pkt gopacket.Packet) { func (mod *Sniffer) onPacketMatched(pkt gopacket.Packet) {
if mainParser(pkt, s.Ctx.Verbose) { if mainParser(pkt, mod.Ctx.Verbose) {
s.Stats.NumDumped++ mod.Stats.NumDumped++
} }
} }
func (s *Sniffer) Configure() error { func (mod *Sniffer) Configure() error {
var err error var err error
if s.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, s.Ctx = s.GetContext(); err != nil { } else if err, mod.Ctx = mod.GetContext(); err != nil {
if s.Ctx != nil { if mod.Ctx != nil {
s.Ctx.Close() mod.Ctx.Close()
s.Ctx = nil mod.Ctx = nil
} }
return err return err
} }
@ -158,66 +158,66 @@ func (s *Sniffer) Configure() error {
return nil return nil
} }
func (s *Sniffer) Start() error { func (mod *Sniffer) Start() error {
if err := s.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return s.SetRunning(true, func() { return mod.SetRunning(true, func() {
s.Stats = NewSnifferStats() mod.Stats = NewSnifferStats()
src := gopacket.NewPacketSource(s.Ctx.Handle, s.Ctx.Handle.LinkType()) src := gopacket.NewPacketSource(mod.Ctx.Handle, mod.Ctx.Handle.LinkType())
s.pktSourceChan = src.Packets() mod.pktSourceChan = src.Packets()
for packet := range s.pktSourceChan { for packet := range mod.pktSourceChan {
if !s.Running() { if !mod.Running() {
s.Debug("end pkt loop (pkt=%v filter='%s')", packet, s.Ctx.Filter) mod.Debug("end pkt loop (pkt=%v filter='%s')", packet, mod.Ctx.Filter)
break break
} }
now := time.Now() now := time.Now()
if s.Stats.FirstPacket.IsZero() { if mod.Stats.FirstPacket.IsZero() {
s.Stats.FirstPacket = now mod.Stats.FirstPacket = now
} }
s.Stats.LastPacket = now mod.Stats.LastPacket = now
isLocal := s.isLocalPacket(packet) isLocal := mod.isLocalPacket(packet)
if isLocal { if isLocal {
s.Stats.NumLocal++ mod.Stats.NumLocal++
} }
if s.fuzzActive { if mod.fuzzActive {
s.doFuzzing(packet) mod.doFuzzing(packet)
} }
if s.Ctx.DumpLocal || !isLocal { if mod.Ctx.DumpLocal || !isLocal {
data := packet.Data() data := packet.Data()
if s.Ctx.Compiled == nil || s.Ctx.Compiled.Match(data) { if mod.Ctx.Compiled == nil || mod.Ctx.Compiled.Match(data) {
s.Stats.NumMatched++ mod.Stats.NumMatched++
s.onPacketMatched(packet) mod.onPacketMatched(packet)
if s.Ctx.OutputWriter != nil { if mod.Ctx.OutputWriter != nil {
s.Ctx.OutputWriter.WritePacket(packet.Metadata().CaptureInfo, data) mod.Ctx.OutputWriter.WritePacket(packet.Metadata().CaptureInfo, data)
s.Stats.NumWrote++ mod.Stats.NumWrote++
} }
} }
} }
} }
s.pktSourceChan = nil mod.pktSourceChan = nil
}) })
} }
func (s *Sniffer) Stop() error { func (mod *Sniffer) Stop() error {
return s.SetRunning(false, func() { return mod.SetRunning(false, func() {
s.Debug("stopping sniffer") mod.Debug("stopping sniffer")
if s.pktSourceChan != nil { if mod.pktSourceChan != nil {
s.Debug("sending nil") mod.Debug("sending nil")
s.pktSourceChan <- nil mod.pktSourceChan <- nil
s.Debug("nil sent") mod.Debug("nil sent")
} }
s.Debug("closing ctx") mod.Debug("closing ctx")
s.Ctx.Close() mod.Ctx.Close()
s.Debug("ctx closed") mod.Debug("ctx closed")
}) })
} }

View file

@ -27,12 +27,12 @@ type SnifferContext struct {
OutputWriter *pcapgo.Writer OutputWriter *pcapgo.Writer
} }
func (s *Sniffer) GetContext() (error, *SnifferContext) { func (mod *Sniffer) GetContext() (error, *SnifferContext) {
var err error var err error
ctx := NewSnifferContext() ctx := NewSnifferContext()
if err, ctx.Source = s.StringParam("net.sniff.source"); err != nil { if err, ctx.Source = mod.StringParam("net.sniff.source"); err != nil {
return err, ctx return err, ctx
} }
@ -42,7 +42,7 @@ func (s *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(s.Session.Interface.Name(), 65536, true, readTimeout); err != nil { if ctx.Handle, err = pcap.OpenLive(mod.Session.Interface.Name(), 65536, true, readTimeout); err != nil {
return err, ctx return err, ctx
} }
} else { } else {
@ -51,15 +51,15 @@ func (s *Sniffer) GetContext() (error, *SnifferContext) {
} }
} }
if err, ctx.Verbose = s.BoolParam("net.sniff.verbose"); err != nil { if err, ctx.Verbose = mod.BoolParam("net.sniff.verbose"); err != nil {
return err, ctx return err, ctx
} }
if err, ctx.DumpLocal = s.BoolParam("net.sniff.local"); err != nil { if err, ctx.DumpLocal = mod.BoolParam("net.sniff.local"); err != nil {
return err, ctx return err, ctx
} }
if err, ctx.Filter = s.StringParam("net.sniff.filter"); err != nil { if err, ctx.Filter = mod.StringParam("net.sniff.filter"); err != nil {
return err, ctx return err, ctx
} else if ctx.Filter != "" { } else if ctx.Filter != "" {
err = ctx.Handle.SetBPFFilter(ctx.Filter) err = ctx.Handle.SetBPFFilter(ctx.Filter)
@ -68,7 +68,7 @@ func (s *Sniffer) GetContext() (error, *SnifferContext) {
} }
} }
if err, ctx.Expression = s.StringParam("net.sniff.regexp"); err != nil { if err, ctx.Expression = mod.StringParam("net.sniff.regexp"); err != nil {
return err, ctx return err, ctx
} else if ctx.Expression != "" { } else if ctx.Expression != "" {
if ctx.Compiled, err = regexp.Compile(ctx.Expression); err != nil { if ctx.Compiled, err = regexp.Compile(ctx.Expression); err != nil {
@ -76,7 +76,7 @@ func (s *Sniffer) GetContext() (error, *SnifferContext) {
} }
} }
if err, ctx.Output = s.StringParam("net.sniff.output"); err != nil { if err, ctx.Output = mod.StringParam("net.sniff.output"); err != nil {
return err, ctx return err, ctx
} else if ctx.Output != "" { } else if ctx.Output != "" {
if ctx.OutputFile, err = os.Create(ctx.Output); err != nil { if ctx.OutputFile, err = os.Create(ctx.Output); err != nil {

View file

@ -21,10 +21,10 @@ var mutators = []func(byte) byte{
}, },
} }
func (s *Sniffer) fuzz(data []byte) int { func (mod *Sniffer) fuzz(data []byte) int {
changes := 0 changes := 0
for off, b := range data { for off, b := range data {
if rand.Float64() > s.fuzzRatio { if rand.Float64() > mod.fuzzRatio {
continue continue
} }
@ -34,19 +34,19 @@ func (s *Sniffer) fuzz(data []byte) int {
return changes return changes
} }
func (s *Sniffer) doFuzzing(pkt gopacket.Packet) { func (mod *Sniffer) doFuzzing(pkt gopacket.Packet) {
if rand.Float64() > s.fuzzRate { if rand.Float64() > mod.fuzzRate {
return return
} }
layersChanged := 0 layersChanged := 0
bytesChanged := 0 bytesChanged := 0
for _, fuzzLayerType := range s.fuzzLayers { for _, fuzzLayerType := range mod.fuzzLayers {
for _, layer := range pkt.Layers() { for _, layer := range pkt.Layers() {
if layer.LayerType().String() == fuzzLayerType { if layer.LayerType().String() == fuzzLayerType {
fuzzData := layer.LayerContents() fuzzData := layer.LayerContents()
changes := s.fuzz(fuzzData) changes := mod.fuzz(fuzzData)
if changes > 0 { if changes > 0 {
layersChanged++ layersChanged++
bytesChanged += changes bytesChanged += changes
@ -57,62 +57,62 @@ func (s *Sniffer) doFuzzing(pkt gopacket.Packet) {
} }
if bytesChanged > 0 { if bytesChanged > 0 {
logFn := s.Info logFn := mod.Info
if s.fuzzSilent { if mod.fuzzSilent {
logFn = s.Debug logFn = mod.Debug
} }
logFn("changed %d bytes in %d layers.", bytesChanged, layersChanged) logFn("changed %d bytes in %d layers.", bytesChanged, layersChanged)
if err := s.Session.Queue.Send(pkt.Data()); err != nil { if err := mod.Session.Queue.Send(pkt.Data()); err != nil {
s.Error("error sending fuzzed packet: %s", err) mod.Error("error sending fuzzed packet: %s", err)
} }
} }
} }
func (s *Sniffer) configureFuzzing() (err error) { func (mod *Sniffer) configureFuzzing() (err error) {
layers := "" layers := ""
if err, layers = s.StringParam("net.fuzz.layers"); err != nil { if err, layers = mod.StringParam("net.fuzz.layers"); err != nil {
return return
} else { } else {
s.fuzzLayers = str.Comma(layers) mod.fuzzLayers = str.Comma(layers)
} }
if err, s.fuzzRate = s.DecParam("net.fuzz.rate"); err != nil { if err, mod.fuzzRate = mod.DecParam("net.fuzz.rate"); err != nil {
return return
} }
if err, s.fuzzRatio = s.DecParam("net.fuzz.ratio"); err != nil { if err, mod.fuzzRatio = mod.DecParam("net.fuzz.ratio"); err != nil {
return return
} }
if err, s.fuzzSilent = s.BoolParam("net.fuzz.silent"); err != nil { if err, mod.fuzzSilent = mod.BoolParam("net.fuzz.silent"); err != nil {
return return
} }
return return
} }
func (s *Sniffer) StartFuzzing() error { func (mod *Sniffer) StartFuzzing() error {
if s.fuzzActive { if mod.fuzzActive {
return nil return nil
} }
if err := s.configureFuzzing(); err != nil { if err := mod.configureFuzzing(); err != nil {
return err return err
} else if !s.Running() { } else if !mod.Running() {
if err := s.Start(); err != nil { if err := mod.Start(); err != nil {
return err return err
} }
} }
s.fuzzActive = true mod.fuzzActive = true
s.Info("active on layer types %s (rate:%f ratio:%f)", strings.Join(s.fuzzLayers, ","), s.fuzzRate, s.fuzzRatio) mod.Info("active on layer types %s (rate:%f ratio:%f)", strings.Join(mod.fuzzLayers, ","), mod.fuzzRate, mod.fuzzRatio)
return nil return nil
} }
func (s *Sniffer) StopFuzzing() error { func (mod *Sniffer) StopFuzzing() error {
s.fuzzActive = false mod.fuzzActive = false
return nil return nil
} }

View file

@ -14,26 +14,26 @@ func NewPacketProxy(s *session.Session) *PacketProxy {
} }
} }
func (pp PacketProxy) Name() string { func (mod PacketProxy) Name() string {
return "packet.proxy" return "packet.proxy"
} }
func (pp PacketProxy) Description() string { func (mod PacketProxy) Description() string {
return "Not supported on this OS" return "Not supported on this OS"
} }
func (pp PacketProxy) Author() string { func (mod PacketProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (pp *PacketProxy) Configure() (err error) { func (mod *PacketProxy) Configure() (err error) {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (pp *PacketProxy) Start() error { func (mod *PacketProxy) Start() error {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (pp *PacketProxy) Stop() error { func (mod *PacketProxy) Stop() error {
return session.ErrNotSupported return session.ErrNotSupported
} }

View file

@ -16,26 +16,26 @@ func NewPacketProxy(s *session.Session) *PacketProxy {
} }
} }
func (pp PacketProxy) Name() string { func (mod PacketProxy) Name() string {
return "packet.proxy" return "packet.proxy"
} }
func (pp PacketProxy) Description() string { func (mod PacketProxy) Description() string {
return "Not supported on this OS" return "Not supported on this OS"
} }
func (pp PacketProxy) Author() string { func (mod PacketProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (pp *PacketProxy) Configure() (err error) { func (mod *PacketProxy) Configure() (err error) {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (pp *PacketProxy) Start() error { func (mod *PacketProxy) Start() error {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (pp *PacketProxy) Stop() error { func (mod *PacketProxy) Stop() error {
return session.ErrNotSupported return session.ErrNotSupported
} }

View file

@ -78,103 +78,103 @@ func NewPacketProxy(s *session.Session) *PacketProxy {
return mod return mod
} }
func (pp PacketProxy) Name() string { func (mod PacketProxy) Name() string {
return "packet.proxy" return "packet.proxy"
} }
func (pp PacketProxy) Description() string { func (mod PacketProxy) Description() string {
return "A Linux only module that relies on NFQUEUEs in order to filter packets." return "A Linux only module that relies on NFQUEUEs in order to filter packets."
} }
func (pp PacketProxy) Author() string { func (mod PacketProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (pp *PacketProxy) destroyQueue() { func (mod *PacketProxy) destroyQueue() {
if pp.queue == nil { if mod.queue == nil {
return return
} }
pp.queue.DestroyQueue() mod.queue.DestroyQueue()
pp.queue.Close() mod.queue.Close()
pp.queue = nil mod.queue = nil
} }
func (pp *PacketProxy) runRule(enable bool) (err error) { func (mod *PacketProxy) runRule(enable bool) (err error) {
action := "-A" action := "-A"
if !enable { if !enable {
action = "-D" action = "-D"
} }
args := []string{ args := []string{
action, pp.chainName, action, mod.chainName,
} }
if pp.rule != "" { if mod.rule != "" {
rule := strings.Split(pp.rule, " ") rule := strings.Split(mod.rule, " ")
args = append(args, rule...) args = append(args, rule...)
} }
args = append(args, []string{ args = append(args, []string{
"-j", "NFQUEUE", "-j", "NFQUEUE",
"--queue-num", fmt.Sprintf("%d", pp.queueNum), "--queue-num", fmt.Sprintf("%d", mod.queueNum),
"--queue-bypass", "--queue-bypass",
}...) }...)
pp.Debug("iptables %s", args) mod.Debug("iptables %s", args)
_, err = core.Exec("iptables", args) _, err = core.Exec("iptables", args)
return return
} }
func (pp *PacketProxy) Configure() (err error) { func (mod *PacketProxy) Configure() (err error) {
golog.SetOutput(ioutil.Discard) golog.SetOutput(ioutil.Discard)
pp.destroyQueue() mod.destroyQueue()
if err, pp.queueNum = pp.IntParam("packet.proxy.queue.num"); err != nil { if err, mod.queueNum = mod.IntParam("packet.proxy.queue.num"); err != nil {
return return
} else if err, pp.chainName = pp.StringParam("packet.proxy.chain"); err != nil { } else if err, mod.chainName = mod.StringParam("packet.proxy.chain"); err != nil {
return return
} else if err, pp.rule = pp.StringParam("packet.proxy.rule"); err != nil { } else if err, mod.rule = mod.StringParam("packet.proxy.rule"); err != nil {
return return
} else if err, pp.pluginPath = pp.StringParam("packet.proxy.plugin"); err != nil { } else if err, mod.pluginPath = mod.StringParam("packet.proxy.plugin"); err != nil {
return return
} }
if pp.pluginPath == "" { if mod.pluginPath == "" {
return fmt.Errorf("The parameter %s can not be empty.", tui.Bold("packet.proxy.plugin")) return fmt.Errorf("The parameter %s can not be empty.", tui.Bold("packet.proxy.plugin"))
} else if !fs.Exists(pp.pluginPath) { } else if !fs.Exists(mod.pluginPath) {
return fmt.Errorf("%s does not exist.", pp.pluginPath) return fmt.Errorf("%s does not exist.", mod.pluginPath)
} }
pp.Info("loading packet proxy plugin from %s ...", pp.pluginPath) mod.Info("loading packet proxy plugin from %s ...", mod.pluginPath)
var ok bool var ok bool
var sym plugin.Symbol var sym plugin.Symbol
if pp.plugin, err = plugin.Open(pp.pluginPath); err != nil { if mod.plugin, err = plugin.Open(mod.pluginPath); err != nil {
return return
} else if sym, err = pp.plugin.Lookup("OnPacket"); err != nil { } else if sym, err = mod.plugin.Lookup("OnPacket"); err != nil {
return return
} else if pp.queueCb, ok = sym.(func(*nfqueue.Payload) int); !ok { } else if mod.queueCb, ok = sym.(func(*nfqueue.Payload) int); !ok {
return fmt.Errorf("Symbol OnPacket is not a valid callback function.") return fmt.Errorf("Symbol OnPacket is not a valid callback function.")
} }
pp.queue = new(nfqueue.Queue) mod.queue = new(nfqueue.Queue)
if err = pp.queue.SetCallback(dummyCallback); err != nil { if err = mod.queue.SetCallback(dummyCallback); err != nil {
return return
} else if err = pp.queue.Init(); err != nil { } else if err = mod.queue.Init(); err != nil {
return return
} else if err = pp.queue.Unbind(syscall.AF_INET); err != nil { } else if err = mod.queue.Unbind(syscall.AF_INET); err != nil {
return return
} else if err = pp.queue.Bind(syscall.AF_INET); err != nil { } else if err = mod.queue.Bind(syscall.AF_INET); err != nil {
return return
} else if err = pp.queue.CreateQueue(pp.queueNum); err != nil { } else if err = mod.queue.CreateQueue(mod.queueNum); err != nil {
return return
} else if err = pp.queue.SetMode(nfqueue.NFQNL_COPY_PACKET); err != nil { } else if err = mod.queue.SetMode(nfqueue.NFQNL_COPY_PACKET); err != nil {
return return
} else if err = pp.runRule(true); err != nil { } else if err = mod.runRule(true); err != nil {
return return
} }
@ -188,28 +188,28 @@ func dummyCallback(payload *nfqueue.Payload) int {
return mod.queueCb(payload) return mod.queueCb(payload)
} }
func (pp *PacketProxy) Start() error { func (mod *PacketProxy) Start() error {
if pp.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err := pp.Configure(); err != nil { } else if err := mod.Configure(); err != nil {
return err return err
} }
return pp.SetRunning(true, func() { return mod.SetRunning(true, func() {
pp.Info("started on queue number %d", pp.queueNum) mod.Info("started on queue number %d", mod.queueNum)
defer pp.destroyQueue() defer mod.destroyQueue()
pp.queue.Loop() mod.queue.Loop()
pp.done <- true mod.done <- true
}) })
} }
func (pp *PacketProxy) Stop() error { func (mod *PacketProxy) Stop() error {
return pp.SetRunning(false, func() { return mod.SetRunning(false, func() {
pp.queue.StopLoop() mod.queue.StopLoop()
pp.runRule(false) mod.runRule(false)
<-pp.done <-mod.done
}) })
} }

View file

@ -14,26 +14,26 @@ func NewPacketProxy(s *session.Session) *PacketProxy {
} }
} }
func (pp PacketProxy) Name() string { func (mod PacketProxy) Name() string {
return "packet.proxy" return "packet.proxy"
} }
func (pp PacketProxy) Description() string { func (mod PacketProxy) Description() string {
return "Not supported on this OS" return "Not supported on this OS"
} }
func (pp PacketProxy) Author() string { func (mod PacketProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (pp *PacketProxy) Configure() (err error) { func (mod *PacketProxy) Configure() (err error) {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (pp *PacketProxy) Start() error { func (mod *PacketProxy) Start() error {
return session.ErrNotSupported return session.ErrNotSupported
} }
func (pp *PacketProxy) Stop() error { func (mod *PacketProxy) Stop() error {
return session.ErrNotSupported return session.ErrNotSupported
} }

View file

@ -1,156 +0,0 @@
package prober
import (
"sync"
"time"
"github.com/bettercap/bettercap/network"
"github.com/bettercap/bettercap/session"
"github.com/malfunkt/iprange"
)
type Probes struct {
NBNS bool
MDNS bool
UPNP bool
WSD bool
}
type Prober struct {
session.SessionModule
throttle int
probes Probes
waitGroup *sync.WaitGroup
}
func NewProber(s *session.Session) *Prober {
p := &Prober{
SessionModule: session.NewSessionModule("net.probe", s),
waitGroup: &sync.WaitGroup{},
}
p.AddParam(session.NewBoolParameter("net.probe.nbns",
"true",
"Enable NetBIOS name service discovery probes."))
p.AddParam(session.NewBoolParameter("net.probe.mdns",
"true",
"Enable mDNS discovery probes."))
p.AddParam(session.NewBoolParameter("net.probe.upnp",
"true",
"Enable UPNP discovery probes."))
p.AddParam(session.NewBoolParameter("net.probe.wsd",
"true",
"Enable WSD discovery probes."))
p.AddParam(session.NewIntParameter("net.probe.throttle",
"10",
"If greater than 0, probe packets will be throttled by this value in milliseconds."))
p.AddHandler(session.NewModuleHandler("net.probe on", "",
"Start network hosts probing in background.",
func(args []string) error {
return p.Start()
}))
p.AddHandler(session.NewModuleHandler("net.probe off", "",
"Stop network hosts probing in background.",
func(args []string) error {
return p.Stop()
}))
return p
}
func (p Prober) Name() string {
return "net.probe"
}
func (p Prober) Description() string {
return "Keep probing for new hosts on the network by sending dummy UDP packets to every possible IP on the subnet."
}
func (p Prober) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>"
}
func (p *Prober) Configure() error {
var err error
if err, p.throttle = p.IntParam("net.probe.throttle"); err != nil {
return err
} else if err, p.probes.NBNS = p.BoolParam("net.probe.nbns"); err != nil {
return err
} else if err, p.probes.MDNS = p.BoolParam("net.probe.mdns"); err != nil {
return err
} else if err, p.probes.UPNP = p.BoolParam("net.probe.upnp"); err != nil {
return err
} else if err, p.probes.WSD = p.BoolParam("net.probe.wsd"); err != nil {
return err
} else {
p.Debug("Throttling packets of %d ms.", p.throttle)
}
return nil
}
func (p *Prober) Start() error {
if err := p.Configure(); err != nil {
return err
}
return p.SetRunning(true, func() {
p.waitGroup.Add(1)
defer p.waitGroup.Done()
if p.Session.Interface.IpAddress == network.MonitorModeAddress {
p.Info("Interface is in monitor mode, skipping net.probe")
return
}
list, err := iprange.Parse(p.Session.Interface.CIDR())
if err != nil {
p.Fatal("%s", err)
}
from := p.Session.Interface.IP
from_hw := p.Session.Interface.HW
addresses := list.Expand()
throttle := time.Duration(p.throttle) * time.Millisecond
for p.Running() {
if p.probes.MDNS {
p.sendProbeMDNS(from, from_hw)
}
if p.probes.UPNP {
p.sendProbeUPNP(from, from_hw)
}
if p.probes.WSD {
p.sendProbeWSD(from, from_hw)
}
for _, ip := range addresses {
if !p.Running() {
return
} else if p.Session.Skip(ip) {
p.Debug("skipping address %s from probing.", ip)
continue
} else if p.probes.NBNS {
p.sendProbeNBNS(from, from_hw, ip)
}
time.Sleep(throttle)
}
time.Sleep(5 * time.Second)
}
})
}
func (p *Prober) Stop() error {
return p.SetRunning(false, func() {
p.waitGroup.Wait()
})
}

View file

@ -1,19 +0,0 @@
package prober
import (
"net"
"github.com/bettercap/bettercap/packets"
)
func (p *Prober) sendProbeMDNS(from net.IP, from_hw net.HardwareAddr) {
err, raw := packets.NewMDNSProbe(from, from_hw)
if err != nil {
p.Error("error while sending mdns probe: %v", err)
return
} else if err := p.Session.Queue.Send(raw); err != nil {
p.Error("error sending mdns packet: %s", err)
} else {
p.Debug("sent %d bytes of MDNS probe", len(raw))
}
}

View file

@ -38,111 +38,111 @@ type SynScanner struct {
} }
func NewSynScanner(s *session.Session) *SynScanner { func NewSynScanner(s *session.Session) *SynScanner {
ss := &SynScanner{ mod := &SynScanner{
SessionModule: session.NewSessionModule("syn.scan", s), SessionModule: session.NewSessionModule("syn.scan", s),
addresses: make([]net.IP, 0), addresses: make([]net.IP, 0),
waitGroup: &sync.WaitGroup{}, waitGroup: &sync.WaitGroup{},
progressEvery: time.Duration(1) * time.Second, progressEvery: time.Duration(1) * time.Second,
} }
ss.AddParam(session.NewIntParameter("syn.scan.show-progress-every", mod.AddParam(session.NewIntParameter("syn.scan.show-progress-every",
"1", "1",
"Period in seconds for the scanning progress reporting.")) "Period in seconds for the scanning progress reporting."))
ss.AddHandler(session.NewModuleHandler("syn.scan stop", "syn\\.scan (stop|off)", mod.AddHandler(session.NewModuleHandler("syn.scan stop", "syn\\.scan (stop|off)",
"Stop the current syn scanning session.", "Stop the current syn scanning session.",
func(args []string) error { func(args []string) error {
if !ss.Running() { if !mod.Running() {
return fmt.Errorf("no syn.scan is running") return fmt.Errorf("no syn.scan is running")
} }
return ss.Stop() return mod.Stop()
})) }))
ss.AddHandler(session.NewModuleHandler("syn.scan IP-RANGE [START-PORT] [END-PORT]", "syn.scan ([^\\s]+) ?(\\d+)?([\\s\\d]*)?", mod.AddHandler(session.NewModuleHandler("syn.scan IP-RANGE [START-PORT] [END-PORT]", "syn.scan ([^\\s]+) ?(\\d+)?([\\s\\d]*)?",
"Perform a syn port scanning against an IP address within the provided ports range.", "Perform a syn port scanning against an IP address within the provided ports range.",
func(args []string) error { func(args []string) error {
period := 0 period := 0
if ss.Running() { if mod.Running() {
return fmt.Errorf("A scan is already running, wait for it to end before starting a new one.") return fmt.Errorf("A scan is already running, wait for it to end before starting a new one.")
} else if err := ss.parseTargets(args[0]); err != nil { } else if err := mod.parseTargets(args[0]); err != nil {
return err return err
} else if err = ss.parsePorts(args); err != nil { } else if err = mod.parsePorts(args); err != nil {
return err return err
} else if err, period = ss.IntParam("syn.scan.show-progress-every"); err != nil { } else if err, period = mod.IntParam("syn.scan.show-progress-every"); err != nil {
return err return err
} else { } else {
ss.progressEvery = time.Duration(period) * time.Second mod.progressEvery = time.Duration(period) * time.Second
} }
return ss.synScan() return mod.synScan()
})) }))
ss.AddHandler(session.NewModuleHandler("syn.scan.progress", "syn\\.scan\\.progress", mod.AddHandler(session.NewModuleHandler("syn.scan.progress", "syn\\.scan\\.progress",
"Print progress of the current syn scanning session.", "Print progress of the current syn scanning session.",
func(args []string) error { func(args []string) error {
if !ss.Running() { if !mod.Running() {
return fmt.Errorf("no syn.scan is running") return fmt.Errorf("no syn.scan is running")
} }
return ss.showProgress() return mod.showProgress()
})) }))
return ss return mod
} }
func (s *SynScanner) parseTargets(arg string) error { func (mod *SynScanner) parseTargets(arg string) error {
if list, err := iprange.Parse(arg); err != nil { if list, err := iprange.Parse(arg); err != nil {
return fmt.Errorf("error while parsing IP range '%s': %s", arg, err) return fmt.Errorf("error while parsing IP range '%s': %s", arg, err)
} else { } else {
s.addresses = list.Expand() mod.addresses = list.Expand()
} }
return nil return nil
} }
func (s *SynScanner) parsePorts(args []string) (err error) { func (mod *SynScanner) parsePorts(args []string) (err error) {
argc := len(args) argc := len(args)
s.stats.totProbes = 0 mod.stats.totProbes = 0
s.stats.doneProbes = 0 mod.stats.doneProbes = 0
s.startPort = 1 mod.startPort = 1
s.endPort = 65535 mod.endPort = 65535
if argc > 1 && str.Trim(args[1]) != "" { if argc > 1 && str.Trim(args[1]) != "" {
if s.startPort, err = strconv.Atoi(str.Trim(args[1])); err != nil { if mod.startPort, err = strconv.Atoi(str.Trim(args[1])); err != nil {
return fmt.Errorf("invalid start port %s: %s", args[1], err) return fmt.Errorf("invalid start port %s: %s", args[1], err)
} else if s.startPort > 65535 { } else if mod.startPort > 65535 {
s.startPort = 65535 mod.startPort = 65535
} }
s.endPort = s.startPort mod.endPort = mod.startPort
} }
if argc > 2 && str.Trim(args[2]) != "" { if argc > 2 && str.Trim(args[2]) != "" {
if s.endPort, err = strconv.Atoi(str.Trim(args[2])); err != nil { if mod.endPort, err = strconv.Atoi(str.Trim(args[2])); err != nil {
return fmt.Errorf("invalid end port %s: %s", args[2], err) return fmt.Errorf("invalid end port %s: %s", args[2], err)
} }
} }
if s.endPort < s.startPort { if mod.endPort < mod.startPort {
return fmt.Errorf("end port %d is greater than start port %d", s.endPort, s.startPort) return fmt.Errorf("end port %d is greater than start port %d", mod.endPort, mod.startPort)
} }
return return
} }
func (s *SynScanner) Name() string { func (mod *SynScanner) Name() string {
return "syn.scan" return "syn.scan"
} }
func (s *SynScanner) Description() string { func (mod *SynScanner) Description() string {
return "A module to perform SYN port scanning." return "A module to perform SYN port scanning."
} }
func (s *SynScanner) Author() string { func (mod *SynScanner) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (s *SynScanner) Configure() error { func (mod *SynScanner) Configure() error {
return nil return nil
} }
func (s *SynScanner) Start() error { func (mod *SynScanner) Start() error {
return nil return nil
} }
@ -153,62 +153,62 @@ func plural(n uint64) string {
return "" return ""
} }
func (s *SynScanner) showProgress() error { func (mod *SynScanner) showProgress() error {
progress := 100.0 * (float64(s.stats.doneProbes) / float64(s.stats.totProbes)) progress := 100.0 * (float64(mod.stats.doneProbes) / float64(mod.stats.totProbes))
s.Info("[%.2f%%] found %d open port%s for %d address%s, sent %d/%d packets in %s", mod.Info("[%.2f%%] found %d open port%s for %d address%s, sent %d/%d packets in %s",
progress, progress,
s.stats.openPorts, mod.stats.openPorts,
plural(s.stats.openPorts), plural(mod.stats.openPorts),
s.stats.numAddresses, mod.stats.numAddresses,
plural(s.stats.numAddresses), plural(mod.stats.numAddresses),
s.stats.doneProbes, mod.stats.doneProbes,
s.stats.totProbes, mod.stats.totProbes,
time.Since(s.stats.started)) time.Since(mod.stats.started))
return nil return nil
} }
func (s *SynScanner) Stop() error { func (mod *SynScanner) Stop() error {
s.Info("stopping ...") mod.Info("stopping ...")
return s.SetRunning(false, func() { return mod.SetRunning(false, func() {
s.waitGroup.Wait() mod.waitGroup.Wait()
s.showProgress() mod.showProgress()
}) })
} }
func (s *SynScanner) synScan() error { func (mod *SynScanner) synScan() error {
s.SetRunning(true, func() { mod.SetRunning(true, func() {
defer s.SetRunning(false, nil) defer mod.SetRunning(false, nil)
s.waitGroup.Add(1) mod.waitGroup.Add(1)
defer s.waitGroup.Done() defer mod.waitGroup.Done()
s.stats.openPorts = 0 mod.stats.openPorts = 0
s.stats.numPorts = uint64(s.endPort - s.startPort + 1) mod.stats.numPorts = uint64(mod.endPort - mod.startPort + 1)
s.stats.started = time.Now() mod.stats.started = time.Now()
s.stats.numAddresses = uint64(len(s.addresses)) mod.stats.numAddresses = uint64(len(mod.addresses))
s.stats.totProbes = s.stats.numAddresses * s.stats.numPorts mod.stats.totProbes = mod.stats.numAddresses * mod.stats.numPorts
s.stats.doneProbes = 0 mod.stats.doneProbes = 0
plural := "es" plural := "es"
if s.stats.numAddresses == 1 { if mod.stats.numAddresses == 1 {
plural = "" plural = ""
} }
if s.stats.numPorts > 1 { if mod.stats.numPorts > 1 {
s.Info("scanning %d address%s from port %d to port %d ...", s.stats.numAddresses, plural, s.startPort, s.endPort) mod.Info("scanning %d address%s from port %d to port %d ...", mod.stats.numAddresses, plural, mod.startPort, mod.endPort)
} else { } else {
s.Info("scanning %d address%s on port %d ...", s.stats.numAddresses, plural, s.startPort) mod.Info("scanning %d address%s on port %d ...", mod.stats.numAddresses, plural, mod.startPort)
} }
// set the collector // set the collector
s.Session.Queue.OnPacket(s.onPacket) mod.Session.Queue.OnPacket(mod.onPacket)
defer s.Session.Queue.OnPacket(nil) defer mod.Session.Queue.OnPacket(nil)
// start to show progress every second // start to show progress every second
go func() { go func() {
for { for {
time.Sleep(s.progressEvery) time.Sleep(mod.progressEvery)
if s.Running() { if mod.Running() {
s.showProgress() mod.showProgress()
} else { } else {
break break
} }
@ -216,34 +216,34 @@ func (s *SynScanner) synScan() error {
}() }()
// start sending SYN packets and wait // start sending SYN packets and wait
for _, address := range s.addresses { for _, address := range mod.addresses {
if !s.Running() { if !mod.Running() {
break break
} }
mac, err := s.Session.FindMAC(address, true) mac, err := mod.Session.FindMAC(address, true)
if err != nil { if err != nil {
atomic.AddUint64(&s.stats.doneProbes, s.stats.numPorts) atomic.AddUint64(&mod.stats.doneProbes, mod.stats.numPorts)
s.Debug("could not get MAC for %s: %s", address.String(), err) mod.Debug("could not get MAC for %s: %s", address.String(), err)
continue continue
} }
for dstPort := s.startPort; dstPort < s.endPort+1; dstPort++ { for dstPort := mod.startPort; dstPort < mod.endPort+1; dstPort++ {
if !s.Running() { if !mod.Running() {
break break
} }
atomic.AddUint64(&s.stats.doneProbes, 1) atomic.AddUint64(&mod.stats.doneProbes, 1)
err, raw := packets.NewTCPSyn(s.Session.Interface.IP, s.Session.Interface.HW, address, mac, synSourcePort, dstPort) err, raw := packets.NewTCPSyn(mod.Session.Interface.IP, mod.Session.Interface.HW, address, mac, synSourcePort, dstPort)
if err != nil { if err != nil {
s.Error("error creating SYN packet: %s", err) mod.Error("error creating SYN packet: %s", err)
continue continue
} }
if err := s.Session.Queue.Send(raw); err != nil { if err := mod.Session.Queue.Send(raw); err != nil {
s.Error("error sending SYN packet: %s", err) mod.Error("error sending SYN packet: %s", err)
} else { } else {
s.Debug("sent %d bytes of SYN packet to %s for port %d", len(raw), address.String(), dstPort) mod.Debug("sent %d bytes of SYN packet to %s for port %d", len(raw), address.String(), dstPort)
} }
time.Sleep(time.Duration(10) * time.Millisecond) time.Sleep(time.Duration(10) * time.Millisecond)

View file

@ -10,8 +10,8 @@ import (
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
) )
func (s *SynScanner) isAddressInRange(ip net.IP) bool { func (mod *SynScanner) isAddressInRange(ip net.IP) bool {
for _, a := range s.addresses { for _, a := range mod.addresses {
if a.Equal(ip) { if a.Equal(ip) {
return true return true
} }
@ -19,7 +19,7 @@ func (s *SynScanner) isAddressInRange(ip net.IP) bool {
return false return false
} }
func (s *SynScanner) onPacket(pkt gopacket.Packet) { func (mod *SynScanner) onPacket(pkt gopacket.Packet) {
var eth layers.Ethernet var eth layers.Ethernet
var ip layers.IPv4 var ip layers.IPv4
var tcp layers.TCP var tcp layers.TCP
@ -37,19 +37,19 @@ func (s *SynScanner) onPacket(pkt gopacket.Packet) {
return return
} }
if s.isAddressInRange(ip.SrcIP) && tcp.DstPort == synSourcePort && tcp.SYN && tcp.ACK { if mod.isAddressInRange(ip.SrcIP) && tcp.DstPort == synSourcePort && tcp.SYN && tcp.ACK {
atomic.AddUint64(&s.stats.openPorts, 1) atomic.AddUint64(&mod.stats.openPorts, 1)
from := ip.SrcIP.String() from := ip.SrcIP.String()
port := int(tcp.SrcPort) port := int(tcp.SrcPort)
var host *network.Endpoint var host *network.Endpoint
if ip.SrcIP.Equal(s.Session.Interface.IP) { if ip.SrcIP.Equal(mod.Session.Interface.IP) {
host = s.Session.Interface host = mod.Session.Interface
} else if ip.SrcIP.Equal(s.Session.Gateway.IP) { } else if ip.SrcIP.Equal(mod.Session.Gateway.IP) {
host = s.Session.Gateway host = mod.Session.Gateway
} else { } else {
host = s.Session.Lan.GetByIp(from) host = mod.Session.Lan.GetByIp(from)
} }
if host != nil { if host != nil {

View file

@ -21,70 +21,70 @@ type TcpProxy struct {
} }
func NewTcpProxy(s *session.Session) *TcpProxy { func NewTcpProxy(s *session.Session) *TcpProxy {
p := &TcpProxy{ mod := &TcpProxy{
SessionModule: session.NewSessionModule("tcp.proxy", s), SessionModule: session.NewSessionModule("tcp.proxy", s),
} }
p.AddParam(session.NewIntParameter("tcp.port", mod.AddParam(session.NewIntParameter("tcp.port",
"443", "443",
"Remote port to redirect when the TCP proxy is activated.")) "Remote port to redirect when the TCP proxy is activated."))
p.AddParam(session.NewStringParameter("tcp.address", mod.AddParam(session.NewStringParameter("tcp.address",
"", "",
session.IPv4Validator, session.IPv4Validator,
"Remote address of the TCP proxy.")) "Remote address of the TCP proxy."))
p.AddParam(session.NewStringParameter("tcp.proxy.address", mod.AddParam(session.NewStringParameter("tcp.proxy.address",
session.ParamIfaceAddress, session.ParamIfaceAddress,
session.IPv4Validator, session.IPv4Validator,
"Address to bind the TCP proxy to.")) "Address to bind the TCP proxy to."))
p.AddParam(session.NewIntParameter("tcp.proxy.port", mod.AddParam(session.NewIntParameter("tcp.proxy.port",
"8443", "8443",
"Port to bind the TCP proxy to.")) "Port to bind the TCP proxy to."))
p.AddParam(session.NewStringParameter("tcp.proxy.script", mod.AddParam(session.NewStringParameter("tcp.proxy.script",
"", "",
"", "",
"Path of a TCP proxy JS script.")) "Path of a TCP proxy JS script."))
p.AddParam(session.NewStringParameter("tcp.tunnel.address", mod.AddParam(session.NewStringParameter("tcp.tunnel.address",
"", "",
"", "",
"Address to redirect the TCP tunnel to (optional).")) "Address to redirect the TCP tunnel to (optional)."))
p.AddParam(session.NewIntParameter("tcp.tunnel.port", mod.AddParam(session.NewIntParameter("tcp.tunnel.port",
"0", "0",
"Port to redirect the TCP tunnel to (optional).")) "Port to redirect the TCP tunnel to (optional)."))
p.AddHandler(session.NewModuleHandler("tcp.proxy on", "", mod.AddHandler(session.NewModuleHandler("tcp.proxy on", "",
"Start TCP proxy.", "Start TCP proxy.",
func(args []string) error { func(args []string) error {
return p.Start() return mod.Start()
})) }))
p.AddHandler(session.NewModuleHandler("tcp.proxy off", "", mod.AddHandler(session.NewModuleHandler("tcp.proxy off", "",
"Stop TCP proxy.", "Stop TCP proxy.",
func(args []string) error { func(args []string) error {
return p.Stop() return mod.Stop()
})) }))
return p return mod
} }
func (p *TcpProxy) Name() string { func (mod *TcpProxy) Name() string {
return "tcp.proxy" return "tcp.proxy"
} }
func (p *TcpProxy) Description() string { func (mod *TcpProxy) Description() string {
return "A full featured TCP proxy and tunnel, all TCP traffic to a given remote address and port will be redirected to it." return "A full featured TCP proxy and tunnel, all TCP traffic to a given remote address and port will be redirected to it."
} }
func (p *TcpProxy) Author() string { func (mod *TcpProxy) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (p *TcpProxy) Configure() error { func (mod *TcpProxy) Configure() error {
var err error var err error
var port int var port int
var proxyPort int var proxyPort int
@ -94,63 +94,63 @@ func (p *TcpProxy) Configure() error {
var tunnelAddress string var tunnelAddress string
var tunnelPort int var tunnelPort int
if p.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, address = p.StringParam("tcp.address"); err != nil { } else if err, address = mod.StringParam("tcp.address"); err != nil {
return err return err
} else if err, proxyAddress = p.StringParam("tcp.proxy.address"); err != nil { } else if err, proxyAddress = mod.StringParam("tcp.proxy.address"); err != nil {
return err return err
} else if err, proxyPort = p.IntParam("tcp.proxy.port"); err != nil { } else if err, proxyPort = mod.IntParam("tcp.proxy.port"); err != nil {
return err return err
} else if err, port = p.IntParam("tcp.port"); err != nil { } else if err, port = mod.IntParam("tcp.port"); err != nil {
return err return err
} else if err, tunnelAddress = p.StringParam("tcp.tunnel.address"); err != nil { } else if err, tunnelAddress = mod.StringParam("tcp.tunnel.address"); err != nil {
return err return err
} else if err, tunnelPort = p.IntParam("tcp.tunnel.port"); err != nil { } else if err, tunnelPort = mod.IntParam("tcp.tunnel.port"); err != nil {
return err return err
} else if err, scriptPath = p.StringParam("tcp.proxy.script"); err != nil { } else if err, scriptPath = mod.StringParam("tcp.proxy.script"); err != nil {
return err return err
} else if p.localAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", proxyAddress, proxyPort)); err != nil { } else if mod.localAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", proxyAddress, proxyPort)); err != nil {
return err return err
} else if p.remoteAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", address, port)); err != nil { } else if mod.remoteAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", address, port)); err != nil {
return err return err
} else if p.tunnelAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", tunnelAddress, tunnelPort)); err != nil { } else if mod.tunnelAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", tunnelAddress, tunnelPort)); err != nil {
return err return err
} else if p.listener, err = net.ListenTCP("tcp", p.localAddr); err != nil { } else if mod.listener, err = net.ListenTCP("tcp", mod.localAddr); err != nil {
return err return err
} }
if scriptPath != "" { if scriptPath != "" {
if err, p.script = LoadTcpProxyScript(scriptPath, p.Session); err != nil { if err, mod.script = LoadTcpProxyScript(scriptPath, mod.Session); err != nil {
return err return err
} else { } else {
p.Debug("script %s loaded.", scriptPath) mod.Debug("script %s loaded.", scriptPath)
} }
} }
if !p.Session.Firewall.IsForwardingEnabled() { if !mod.Session.Firewall.IsForwardingEnabled() {
p.Info("enabling forwarding.") mod.Info("enabling forwarding.")
p.Session.Firewall.EnableForwarding(true) mod.Session.Firewall.EnableForwarding(true)
} }
p.Redirection = firewall.NewRedirection(p.Session.Interface.Name(), mod.Redirection = firewall.NewRedirection(mod.Session.Interface.Name(),
"TCP", "TCP",
port, port,
proxyAddress, proxyAddress,
proxyPort) proxyPort)
p.Redirection.SrcAddress = address mod.Redirection.SrcAddress = address
if err := p.Session.Firewall.EnableRedirection(p.Redirection, true); err != nil { if err := mod.Session.Firewall.EnableRedirection(mod.Redirection, true); err != nil {
return err return err
} }
p.Debug("applied redirection %s", p.Redirection.String()) mod.Debug("applied redirection %s", mod.Redirection.String())
return nil return nil
} }
func (p *TcpProxy) doPipe(from, to net.Addr, src, dst io.ReadWriter, wg *sync.WaitGroup) { func (mod *TcpProxy) doPipe(from, to net.Addr, src, dst io.ReadWriter, wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
buff := make([]byte, 0xffff) buff := make([]byte, 0xffff)
@ -158,18 +158,18 @@ func (p *TcpProxy) doPipe(from, to net.Addr, src, dst io.ReadWriter, wg *sync.Wa
n, err := src.Read(buff) n, err := src.Read(buff)
if err != nil { if err != nil {
if err.Error() != "EOF" { if err.Error() != "EOF" {
p.Warning("read failed: %s", err) mod.Warning("read failed: %s", err)
} }
return return
} }
b := buff[:n] b := buff[:n]
if p.script != nil { if mod.script != nil {
ret := p.script.OnData(from, to, b) ret := mod.script.OnData(from, to, b)
if ret != nil { if ret != nil {
nret := len(ret) nret := len(ret)
p.Info("overriding %d bytes of data from %s to %s with %d bytes of new data.", mod.Info("overriding %d bytes of data from %s to %s with %d bytes of new data.",
n, from.String(), to.String(), nret) n, from.String(), to.String(), nret)
b = make([]byte, nret) b = make([]byte, nret)
copy(b, ret) copy(b, ret)
@ -178,28 +178,28 @@ func (p *TcpProxy) doPipe(from, to net.Addr, src, dst io.ReadWriter, wg *sync.Wa
n, err = dst.Write(b) n, err = dst.Write(b)
if err != nil { if err != nil {
p.Warning("write failed: %s", err) mod.Warning("write failed: %s", err)
return return
} }
p.Debug("%s -> %s : %d bytes", from.String(), to.String(), n) mod.Debug("%s -> %s : %d bytes", from.String(), to.String(), n)
} }
} }
func (p *TcpProxy) handleConnection(c *net.TCPConn) { func (mod *TcpProxy) handleConnection(c *net.TCPConn) {
defer c.Close() defer c.Close()
p.Info("got a connection from %s", c.RemoteAddr().String()) mod.Info("got a connection from %s", c.RemoteAddr().String())
// tcp tunnel enabled // tcp tunnel enabled
if p.tunnelAddr.IP.To4() != nil { if mod.tunnelAddr.IP.To4() != nil {
p.Info("tcp tunnel started ( %s -> %s )", p.remoteAddr.String(), p.tunnelAddr.String()) mod.Info("tcp tunnel started ( %s -> %s )", mod.remoteAddr.String(), mod.tunnelAddr.String())
p.remoteAddr = p.tunnelAddr mod.remoteAddr = mod.tunnelAddr
} }
remote, err := net.DialTCP("tcp", nil, p.remoteAddr) remote, err := net.DialTCP("tcp", nil, mod.remoteAddr)
if err != nil { if err != nil {
p.Warning("error while connecting to remote %s: %s", p.remoteAddr.String(), err) mod.Warning("error while connecting to remote %s: %s", mod.remoteAddr.String(), err)
return return
} }
defer remote.Close() defer remote.Close()
@ -208,43 +208,43 @@ func (p *TcpProxy) handleConnection(c *net.TCPConn) {
wg.Add(2) wg.Add(2)
// start pipeing // start pipeing
go p.doPipe(c.RemoteAddr(), p.remoteAddr, c, remote, &wg) go mod.doPipe(c.RemoteAddr(), mod.remoteAddr, c, remote, &wg)
go p.doPipe(p.remoteAddr, c.RemoteAddr(), remote, c, &wg) go mod.doPipe(mod.remoteAddr, c.RemoteAddr(), remote, c, &wg)
wg.Wait() wg.Wait()
} }
func (p *TcpProxy) Start() error { func (mod *TcpProxy) Start() error {
if err := p.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return p.SetRunning(true, func() { return mod.SetRunning(true, func() {
p.Info("started ( x -> %s -> %s )", p.localAddr.String(), p.remoteAddr.String()) mod.Info("started ( x -> %s -> %s )", mod.localAddr.String(), mod.remoteAddr.String())
for p.Running() { for mod.Running() {
conn, err := p.listener.AcceptTCP() conn, err := mod.listener.AcceptTCP()
if err != nil { if err != nil {
p.Warning("error while accepting TCP connection: %s", err) mod.Warning("error while accepting TCP connection: %s", err)
continue continue
} }
go p.handleConnection(conn) go mod.handleConnection(conn)
} }
}) })
} }
func (p *TcpProxy) Stop() error { func (mod *TcpProxy) Stop() error {
if p.Redirection != nil { if mod.Redirection != nil {
p.Debug("disabling redirection %s", p.Redirection.String()) mod.Debug("disabling redirection %s", mod.Redirection.String())
if err := p.Session.Firewall.EnableRedirection(p.Redirection, false); err != nil { if err := mod.Session.Firewall.EnableRedirection(mod.Redirection, false); err != nil {
return err return err
} }
p.Redirection = nil mod.Redirection = nil
} }
return p.SetRunning(false, func() { return mod.SetRunning(false, func() {
p.listener.Close() mod.listener.Close()
}) })
} }

View file

@ -13,87 +13,87 @@ type Ticker struct {
} }
func NewTicker(s *session.Session) *Ticker { func NewTicker(s *session.Session) *Ticker {
t := &Ticker{ mod := &Ticker{
SessionModule: session.NewSessionModule("ticker", s), SessionModule: session.NewSessionModule("ticker", s),
} }
t.AddParam(session.NewStringParameter("ticker.commands", mod.AddParam(session.NewStringParameter("ticker.commands",
"clear; net.show; events.show 20", "clear; net.show; events.show 20",
"", "",
"List of commands separated by a ;")) "List of commands separated by a ;"))
t.AddParam(session.NewIntParameter("ticker.period", mod.AddParam(session.NewIntParameter("ticker.period",
"1", "1",
"Ticker period in seconds")) "Ticker period in seconds"))
t.AddHandler(session.NewModuleHandler("ticker on", "", mod.AddHandler(session.NewModuleHandler("ticker on", "",
"Start the ticker.", "Start the ticker.",
func(args []string) error { func(args []string) error {
return t.Start() return mod.Start()
})) }))
t.AddHandler(session.NewModuleHandler("ticker off", "", mod.AddHandler(session.NewModuleHandler("ticker off", "",
"Stop the ticker.", "Stop the ticker.",
func(args []string) error { func(args []string) error {
return t.Stop() return mod.Stop()
})) }))
return t return mod
} }
func (t *Ticker) Name() string { func (mod *Ticker) Name() string {
return "ticker" return "ticker"
} }
func (t *Ticker) Description() string { func (mod *Ticker) Description() string {
return "A module to execute one or more commands every given amount of seconds." return "A module to execute one or more commands every given amount of seconds."
} }
func (t *Ticker) Author() string { func (mod *Ticker) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (t *Ticker) Configure() error { func (mod *Ticker) Configure() error {
var err error var err error
var commands string var commands string
var period int var period int
if t.Running() { if mod.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} else if err, commands = t.StringParam("ticker.commands"); err != nil { } else if err, commands = mod.StringParam("ticker.commands"); err != nil {
return err return err
} else if err, period = t.IntParam("ticker.period"); err != nil { } else if err, period = mod.IntParam("ticker.period"); err != nil {
return err return err
} }
t.Commands = session.ParseCommands(commands) mod.Commands = session.ParseCommands(commands)
t.Period = time.Duration(period) * time.Second mod.Period = time.Duration(period) * time.Second
return nil return nil
} }
func (t *Ticker) Start() error { func (mod *Ticker) Start() error {
if err := t.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
return t.SetRunning(true, func() { return mod.SetRunning(true, func() {
t.Info("running with period %.fs", t.Period.Seconds()) mod.Info("running with period %.fs", mod.Period.Seconds())
tick := time.NewTicker(t.Period) tick := time.NewTicker(mod.Period)
for range tick.C { for range tick.C {
if !t.Running() { if !mod.Running() {
break break
} }
for _, cmd := range t.Commands { for _, cmd := range mod.Commands {
if err := t.Session.Run(cmd); err != nil { if err := mod.Session.Run(cmd); err != nil {
t.Error("%s", err) mod.Error("%s", err)
} }
} }
} }
}) })
} }
func (t *Ticker) Stop() error { func (mod *Ticker) Stop() error {
return t.SetRunning(false, nil) return mod.SetRunning(false, nil)
} }

View file

@ -20,41 +20,42 @@ type UpdateModule struct {
} }
func NewUpdateModule(s *session.Session) *UpdateModule { func NewUpdateModule(s *session.Session) *UpdateModule {
u := &UpdateModule{ mod := &UpdateModule{
SessionModule: session.NewSessionModule("update", s), SessionModule: session.NewSessionModule("update", s),
client: github.NewClient(nil), client: github.NewClient(nil),
} }
u.AddHandler(session.NewModuleHandler("update.check on", "", mod.AddHandler(session.NewModuleHandler("update.check on", "",
"Check latest available stable version and compare it with the one being used.", "Check latest available stable version and compare it with the one being used.",
func(args []string) error { func(args []string) error {
return u.Start() return mod.Start()
})) }))
return u return mod
} }
func (u *UpdateModule) Name() string {
func (mod *UpdateModule) Name() string {
return "update" return "update"
} }
func (u *UpdateModule) Description() string { func (mod *UpdateModule) Description() string {
return "A module to check for bettercap's updates." return "A module to check for bettercap's updates."
} }
func (u *UpdateModule) Author() string { func (mod *UpdateModule) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (u *UpdateModule) Configure() error { func (mod *UpdateModule) Configure() error {
return nil return nil
} }
func (u *UpdateModule) Stop() error { func (mod *UpdateModule) Stop() error {
return nil return nil
} }
func (u *UpdateModule) versionToNum(ver string) float64 { func (mod *UpdateModule) versionToNum(ver string) float64 {
if ver[0] == 'v' { if ver[0] == 'v' {
ver = ver[1:] ver = ver[1:]
} }
@ -77,21 +78,21 @@ func (u *UpdateModule) versionToNum(ver string) float64 {
return n return n
} }
func (u *UpdateModule) Start() error { func (mod *UpdateModule) Start() error {
return u.SetRunning(true, func() { return mod.SetRunning(true, func() {
defer u.SetRunning(false, nil) defer mod.SetRunning(false, nil)
u.Info("checking latest stable release ...") mod.Info("checking latest stable release ...")
if releases, _, err := u.client.Repositories.ListReleases(context.Background(), "bettercap", "bettercap", nil); err == nil { if releases, _, err := mod.client.Repositories.ListReleases(context.Background(), "bettercap", "bettercap", nil); err == nil {
latest := releases[0] latest := releases[0]
if u.versionToNum(core.Version) < u.versionToNum(*latest.TagName) { if mod.versionToNum(core.Version) < mod.versionToNum(*latest.TagName) {
u.Session.Events.Add("update.available", latest) mod.Session.Events.Add("update.available", latest)
} else { } else {
u.Info("you are running %s which is the latest stable version.", tui.Bold(core.Version)) mod.Info("you are running %s which is the latest stable version.", tui.Bold(core.Version))
} }
} else { } else {
u.Error("error while fetching latest release info from GitHub: %s", err) mod.Error("error while fetching latest release info from GitHub: %s", err)
} }
}) })
} }

View file

@ -1,4 +1,4 @@
package modules package utils
import ( import (
"encoding/base64" "encoding/base64"

View file

@ -53,7 +53,7 @@ type WiFiModule struct {
} }
func NewWiFiModule(s *session.Session) *WiFiModule { func NewWiFiModule(s *session.Session) *WiFiModule {
w := &WiFiModule{ mod := &WiFiModule{
SessionModule: session.NewSessionModule("wifi", s), SessionModule: session.NewSessionModule("wifi", s),
minRSSI: -200, minRSSI: -200,
channel: 0, channel: 0,
@ -74,47 +74,47 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
chanLock: &sync.Mutex{}, chanLock: &sync.Mutex{},
} }
w.AddHandler(session.NewModuleHandler("wifi.recon on", "", mod.AddHandler(session.NewModuleHandler("wifi.recon on", "",
"Start 802.11 wireless base stations discovery and channel hopping.", "Start 802.11 wireless base stations discovery and channel hopping.",
func(args []string) error { func(args []string) error {
return w.Start() return mod.Start()
})) }))
w.AddHandler(session.NewModuleHandler("wifi.recon off", "", mod.AddHandler(session.NewModuleHandler("wifi.recon off", "",
"Stop 802.11 wireless base stations discovery and channel hopping.", "Stop 802.11 wireless base stations discovery and channel hopping.",
func(args []string) error { func(args []string) error {
return w.Stop() return mod.Stop()
})) }))
w.AddHandler(session.NewModuleHandler("wifi.recon MAC", "wifi.recon ((?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2}))", mod.AddHandler(session.NewModuleHandler("wifi.recon MAC", "wifi.recon ((?:[0-9A-Fa-f]{2}[:-]){5}(?:[0-9A-Fa-f]{2}))",
"Set 802.11 base station address to filter for.", "Set 802.11 base station address to filter for.",
func(args []string) error { func(args []string) error {
bssid, err := net.ParseMAC(args[0]) bssid, err := net.ParseMAC(args[0])
if err != nil { if err != nil {
return err return err
} else if ap, found := w.Session.WiFi.Get(bssid.String()); found { } else if ap, found := mod.Session.WiFi.Get(bssid.String()); found {
w.ap = ap mod.ap = ap
w.stickChan = ap.Channel() mod.stickChan = ap.Channel()
return nil return nil
} }
return fmt.Errorf("Could not find station with BSSID %s", args[0]) return fmt.Errorf("Could not find station with BSSID %s", args[0])
})) }))
w.AddHandler(session.NewModuleHandler("wifi.recon clear", "", mod.AddHandler(session.NewModuleHandler("wifi.recon clear", "",
"Remove the 802.11 base station filter.", "Remove the 802.11 base station filter.",
func(args []string) (err error) { func(args []string) (err error) {
w.ap = nil mod.ap = nil
w.stickChan = 0 mod.stickChan = 0
w.frequencies, err = network.GetSupportedFrequencies(w.Session.Interface.Name()) mod.frequencies, err = network.GetSupportedFrequencies(mod.Session.Interface.Name())
w.hopChanges <- true mod.hopChanges <- true
return err return err
})) }))
w.AddParam(session.NewIntParameter("wifi.rssi.min", mod.AddParam(session.NewIntParameter("wifi.rssi.min",
"-200", "-200",
"Minimum WiFi signal strength in dBm.")) "Minimum WiFi signal strength in dBm."))
w.AddHandler(session.NewModuleHandler("wifi.deauth BSSID", `wifi\.deauth ((?:[a-fA-F0-9:]{11,})|all|\*)`, mod.AddHandler(session.NewModuleHandler("wifi.deauth BSSID", `wifi\.deauth ((?:[a-fA-F0-9:]{11,})|all|\*)`,
"Start a 802.11 deauth attack, if an access point BSSID is provided, every client will be deauthenticated, otherwise only the selected client. Use 'all', '*' or a broadcast BSSID (ff:ff:ff:ff:ff:ff) to iterate every access point with at least one client and start a deauth attack for each one.", "Start a 802.11 deauth attack, if an access point BSSID is provided, every client will be deauthenticated, otherwise only the selected client. Use 'all', '*' or a broadcast BSSID (ff:ff:ff:ff:ff:ff) to iterate every access point with at least one client and start a deauth attack for each one.",
func(args []string) error { func(args []string) error {
if args[0] == "all" || args[0] == "*" { if args[0] == "all" || args[0] == "*" {
@ -124,23 +124,23 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
if err != nil { if err != nil {
return err return err
} }
return w.startDeauth(bssid) return mod.startDeauth(bssid)
})) }))
w.AddParam(session.NewStringParameter("wifi.deauth.skip", mod.AddParam(session.NewStringParameter("wifi.deauth.skip",
"", "",
"", "",
"Comma separated list of BSSID to skip while sending deauth packets.")) "Comma separated list of BSSID to skip while sending deauth packets."))
w.AddParam(session.NewBoolParameter("wifi.deauth.silent", mod.AddParam(session.NewBoolParameter("wifi.deauth.silent",
"false", "false",
"If true, messages from wifi.deauth will be suppressed.")) "If true, messages from wifi.deauth will be suppressed."))
w.AddParam(session.NewBoolParameter("wifi.deauth.open", mod.AddParam(session.NewBoolParameter("wifi.deauth.open",
"true", "true",
"Send wifi deauth packets to open networks.")) "Send wifi deauth packets to open networks."))
w.AddHandler(session.NewModuleHandler("wifi.assoc BSSID", `wifi\.assoc ((?:[a-fA-F0-9:]{11,})|all|\*)`, mod.AddHandler(session.NewModuleHandler("wifi.assoc BSSID", `wifi\.assoc ((?:[a-fA-F0-9:]{11,})|all|\*)`,
"Send an association request to the selected BSSID in order to receive a RSN PMKID key. Use 'all', '*' or a broadcast BSSID (ff:ff:ff:ff:ff:ff) to iterate for every access point.", "Send an association request to the selected BSSID in order to receive a RSN PMKID key. Use 'all', '*' or a broadcast BSSID (ff:ff:ff:ff:ff:ff) to iterate for every access point.",
func(args []string) error { func(args []string) error {
if args[0] == "all" || args[0] == "*" { if args[0] == "all" || args[0] == "*" {
@ -150,81 +150,81 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
if err != nil { if err != nil {
return err return err
} }
return w.startAssoc(bssid) return mod.startAssoc(bssid)
})) }))
w.AddParam(session.NewStringParameter("wifi.assoc.skip", mod.AddParam(session.NewStringParameter("wifi.assoc.skip",
"", "",
"", "",
"Comma separated list of BSSID to skip while sending association requests.")) "Comma separated list of BSSID to skip while sending association requests."))
w.AddParam(session.NewBoolParameter("wifi.assoc.silent", mod.AddParam(session.NewBoolParameter("wifi.assoc.silent",
"false", "false",
"If true, messages from wifi.assoc will be suppressed.")) "If true, messages from wifi.assoc will be suppressed."))
w.AddParam(session.NewBoolParameter("wifi.assoc.open", mod.AddParam(session.NewBoolParameter("wifi.assoc.open",
"false", "false",
"Send association requests to open networks.")) "Send association requests to open networks."))
w.AddHandler(session.NewModuleHandler("wifi.ap", "", mod.AddHandler(session.NewModuleHandler("wifi.ap", "",
"Inject fake management beacons in order to create a rogue access point.", "Inject fake management beacons in order to create a rogue access point.",
func(args []string) error { func(args []string) error {
if err := w.parseApConfig(); err != nil { if err := mod.parseApConfig(); err != nil {
return err return err
} else { } else {
return w.startAp() return mod.startAp()
} }
})) }))
w.AddParam(session.NewStringParameter("wifi.handshakes.file", mod.AddParam(session.NewStringParameter("wifi.handshakes.file",
"~/bettercap-wifi-handshakes.pcap", "~/bettercap-wifi-handshakes.pcap",
"", "",
"File path of the pcap file to save handshakes to.")) "File path of the pcap file to save handshakes to."))
w.AddParam(session.NewStringParameter("wifi.ap.ssid", mod.AddParam(session.NewStringParameter("wifi.ap.ssid",
"FreeWiFi", "FreeWiFi",
"", "",
"SSID of the fake access point.")) "SSID of the fake access point."))
w.AddParam(session.NewStringParameter("wifi.ap.bssid", mod.AddParam(session.NewStringParameter("wifi.ap.bssid",
session.ParamRandomMAC, session.ParamRandomMAC,
"[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}", "[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}",
"BSSID of the fake access point.")) "BSSID of the fake access point."))
w.AddParam(session.NewIntParameter("wifi.ap.channel", mod.AddParam(session.NewIntParameter("wifi.ap.channel",
"1", "1",
"Channel of the fake access point.")) "Channel of the fake access point."))
w.AddParam(session.NewBoolParameter("wifi.ap.encryption", mod.AddParam(session.NewBoolParameter("wifi.ap.encryption",
"true", "true",
"If true, the fake access point will use WPA2, otherwise it'll result as an open AP.")) "If true, the fake access point will use WPA2, otherwise it'll result as an open AP."))
w.AddHandler(session.NewModuleHandler("wifi.show.wps BSSID", mod.AddHandler(session.NewModuleHandler("wifi.show.wps BSSID",
`wifi\.show\.wps ((?:[a-fA-F0-9:]{11,})|all|\*)`, `wifi\.show\.wps ((?:[a-fA-F0-9:]{11,})|all|\*)`,
"Show WPS information about a given station (use 'all', '*' or a broadcast BSSID for all).", "Show WPS information about a given station (use 'all', '*' or a broadcast BSSID for all).",
func(args []string) error { func(args []string) error {
if args[0] == "all" || args[0] == "*" { if args[0] == "all" || args[0] == "*" {
args[0] = "ff:ff:ff:ff:ff:ff" args[0] = "ff:ff:ff:ff:ff:ff"
} }
return w.ShowWPS(args[0]) return mod.ShowWPS(args[0])
})) }))
w.AddHandler(session.NewModuleHandler("wifi.show", "", mod.AddHandler(session.NewModuleHandler("wifi.show", "",
"Show current wireless stations list (default sorting by essid).", "Show current wireless stations list (default sorting by essid).",
func(args []string) error { func(args []string) error {
return w.Show() return mod.Show()
})) }))
w.selector = utils.ViewSelectorFor(&w.SessionModule, "wifi.show", mod.selector = utils.ViewSelectorFor(&mod.SessionModule, "wifi.show",
[]string{"rssi", "bssid", "essid", "channel", "encryption", "clients", "seen", "sent", "rcvd"}, "rssi asc") []string{"rssi", "bssid", "essid", "channel", "encryption", "clients", "seen", "sent", "rcvd"}, "rssi asc")
w.AddHandler(session.NewModuleHandler("wifi.recon.channel", `wifi\.recon\.channel[\s]+([0-9]+(?:[, ]+[0-9]+)*|clear)`, mod.AddHandler(session.NewModuleHandler("wifi.recon.channel", `wifi\.recon\.channel[\s]+([0-9]+(?:[, ]+[0-9]+)*|clear)`,
"WiFi channels (comma separated) or 'clear' for channel hopping.", "WiFi channels (comma separated) or 'clear' for channel hopping.",
func(args []string) (err error) { func(args []string) (err error) {
freqs := []int{} freqs := []int{}
if args[0] != "clear" { if args[0] != "clear" {
w.Debug("setting hopping channels to %s", args[0]) mod.Debug("setting hopping channels to %s", args[0])
for _, s := range str.Comma(args[0]) { for _, s := range str.Comma(args[0]) {
if ch, err := strconv.Atoi(s); err != nil { if ch, err := strconv.Atoi(s); err != nil {
return err return err
@ -239,48 +239,48 @@ func NewWiFiModule(s *session.Session) *WiFiModule {
} }
if len(freqs) == 0 { if len(freqs) == 0 {
w.Debug("resetting hopping channels") mod.Debug("resetting hopping channels")
if freqs, err = network.GetSupportedFrequencies(w.Session.Interface.Name()); err != nil { if freqs, err = network.GetSupportedFrequencies(mod.Session.Interface.Name()); err != nil {
return err return err
} }
} }
w.Debug("new frequencies: %v", freqs) mod.Debug("new frequencies: %v", freqs)
w.frequencies = freqs mod.frequencies = freqs
// if wifi.recon is not running, this would block forever // if wifi.recon is not running, this would block forever
if w.Running() { if mod.Running() {
w.hopChanges <- true mod.hopChanges <- true
} }
return nil return nil
})) }))
w.AddParam(session.NewStringParameter("wifi.source.file", mod.AddParam(session.NewStringParameter("wifi.source.file",
"", "",
"", "",
"If set, the wifi module will read from this pcap file instead of the hardware interface.")) "If set, the wifi module will read from this pcap file instead of the hardware interface."))
w.AddParam(session.NewIntParameter("wifi.hop.period", mod.AddParam(session.NewIntParameter("wifi.hop.period",
"250", "250",
"If channel hopping is enabled (empty wifi.recon.channel), this is the time in milliseconds the algorithm will hop on every channel (it'll be doubled if both 2.4 and 5.0 bands are available).")) "If channel hopping is enabled (empty wifi.recon.channel), this is the time in milliseconds the algorithm will hop on every channel (it'll be doubled if both 2.4 and 5.0 bands are available)."))
w.AddParam(session.NewBoolParameter("wifi.skip-broken", mod.AddParam(session.NewBoolParameter("wifi.skip-broken",
"true", "true",
"If true, dot11 packets with an invalid checksum will be skipped.")) "If true, dot11 packets with an invalid checksum will be skipped."))
return w return mod
} }
func (w WiFiModule) Name() string { func (mod WiFiModule) Name() string {
return "wifi" return "wifi"
} }
func (w WiFiModule) Description() string { func (mod WiFiModule) Description() string {
return "A module to monitor and perform wireless attacks on 802.11." return "A module to monitor and perform wireless attacks on 802.11."
} }
func (w WiFiModule) Author() string { func (mod WiFiModule) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com> && Gianluca Braga <matrix86@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com> && Gianluca Braga <matrix86@gmail.com>"
} }
@ -290,31 +290,31 @@ const (
ErrIfaceNotUp = "Interface Not Up" ErrIfaceNotUp = "Interface Not Up"
) )
func (w *WiFiModule) Configure() error { func (mod *WiFiModule) Configure() error {
var hopPeriod int var hopPeriod int
var err error var err error
if err, w.source = w.StringParam("wifi.source.file"); err != nil { if err, mod.source = mod.StringParam("wifi.source.file"); err != nil {
return err return err
} }
if err, w.shakesFile = w.StringParam("wifi.handshakes.file"); err != nil { if err, mod.shakesFile = mod.StringParam("wifi.handshakes.file"); err != nil {
return err return err
} else if w.shakesFile != "" { } else if mod.shakesFile != "" {
if w.shakesFile, err = fs.Expand(w.shakesFile); err != nil { if mod.shakesFile, err = fs.Expand(mod.shakesFile); err != nil {
return err return err
} }
} }
if err, w.minRSSI = w.IntParam("wifi.rssi.min"); err != nil { if err, mod.minRSSI = mod.IntParam("wifi.rssi.min"); err != nil {
return err return err
} }
ifName := w.Session.Interface.Name() ifName := mod.Session.Interface.Name()
if w.source != "" { if mod.source != "" {
if w.handle, err = pcap.OpenOffline(w.source); err != nil { if mod.handle, err = pcap.OpenOffline(mod.source); err != nil {
return fmt.Errorf("error while opening file %s: %s", w.source, err) return fmt.Errorf("error while opening file %s: %s", mod.source, err)
} }
} else { } else {
for retry := 0; ; retry++ { for retry := 0; ; retry++ {
@ -336,9 +336,9 @@ func (w *WiFiModule) Configure() error {
readTimeout := 500 * time.Millisecond readTimeout := 500 * time.Millisecond
if err = ihandle.SetTimeout(readTimeout); err != nil { if err = ihandle.SetTimeout(readTimeout); err != nil {
return fmt.Errorf("error while setting timeout: %s", err) return fmt.Errorf("error while setting timeout: %s", err)
} else if w.handle, err = ihandle.Activate(); err != nil { } else if mod.handle, err = ihandle.Activate(); err != nil {
if retry == 0 && err.Error() == ErrIfaceNotUp { if retry == 0 && err.Error() == ErrIfaceNotUp {
w.Warning("interface %s is down, bringing it up ...", ifName) mod.Warning("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
} }
@ -351,39 +351,39 @@ func (w *WiFiModule) Configure() error {
} }
} }
if err, w.skipBroken = w.BoolParam("wifi.skip-broken"); err != nil { if err, mod.skipBroken = mod.BoolParam("wifi.skip-broken"); err != nil {
return err return err
} else if err, hopPeriod = w.IntParam("wifi.hop.period"); err != nil { } else if err, hopPeriod = mod.IntParam("wifi.hop.period"); err != nil {
return err return err
} }
w.hopPeriod = time.Duration(hopPeriod) * time.Millisecond mod.hopPeriod = time.Duration(hopPeriod) * time.Millisecond
if w.source == "" { if mod.source == "" {
// No channels setted, retrieve frequencies supported by the card // No channels setted, retrieve frequencies supported by the card
if len(w.frequencies) == 0 { if len(mod.frequencies) == 0 {
if w.frequencies, err = network.GetSupportedFrequencies(ifName); err != nil { if mod.frequencies, err = network.GetSupportedFrequencies(ifName); err != nil {
return fmt.Errorf("error while getting supported frequencies of %s: %s", ifName, err) return fmt.Errorf("error while getting supported frequencies of %s: %s", ifName, err)
} }
w.Debug("wifi supported frequencies: %v", w.frequencies) mod.Debug("wifi supported frequencies: %v", mod.frequencies)
// we need to start somewhere, this is just to check if // we need to start somewhere, this is just to check if
// this OS supports switching channel programmatically. // this OS supports switching channel programmatically.
if err = network.SetInterfaceChannel(ifName, 1); err != nil { if err = network.SetInterfaceChannel(ifName, 1); err != nil {
return fmt.Errorf("error while initializing %s to channel 1: %s", ifName, err) return fmt.Errorf("error while initializing %s to channel 1: %s", ifName, err)
} }
w.Info("started (min rssi: %d dBm)", w.minRSSI) mod.Info("started (min rssi: %d dBm)", mod.minRSSI)
} }
} }
return nil return nil
} }
func (w *WiFiModule) updateInfo(dot11 *layers.Dot11, packet gopacket.Packet) { func (mod *WiFiModule) updateInfo(dot11 *layers.Dot11, packet gopacket.Packet) {
if ok, enc, cipher, auth := packets.Dot11ParseEncryption(packet, dot11); ok { if ok, enc, cipher, auth := packets.Dot11ParseEncryption(packet, dot11); ok {
bssid := dot11.Address3.String() bssid := dot11.Address3.String()
if station, found := w.Session.WiFi.Get(bssid); found { if station, found := mod.Session.WiFi.Get(bssid); found {
station.Encryption = enc station.Encryption = enc
station.Cipher = cipher station.Cipher = cipher
station.Authentication = auth station.Authentication = auth
@ -391,7 +391,7 @@ func (w *WiFiModule) updateInfo(dot11 *layers.Dot11, packet gopacket.Packet) {
} }
if ok, bssid, info := packets.Dot11ParseWPS(packet, dot11); ok { if ok, bssid, info := packets.Dot11ParseWPS(packet, dot11); ok {
if station, found := w.Session.WiFi.Get(bssid.String()); found { if station, found := mod.Session.WiFi.Get(bssid.String()); found {
for name, value := range info { for name, value := range info {
station.WPS[name] = value station.WPS[name] = value
} }
@ -399,84 +399,84 @@ func (w *WiFiModule) updateInfo(dot11 *layers.Dot11, packet gopacket.Packet) {
} }
} }
func (w *WiFiModule) updateStats(dot11 *layers.Dot11, packet gopacket.Packet) { func (mod *WiFiModule) updateStats(dot11 *layers.Dot11, packet gopacket.Packet) {
// collect stats from data frames // collect stats from data frames
if dot11.Type.MainType() == layers.Dot11TypeData { if dot11.Type.MainType() == layers.Dot11TypeData {
bytes := uint64(len(packet.Data())) bytes := uint64(len(packet.Data()))
dst := dot11.Address1.String() dst := dot11.Address1.String()
if station, found := w.Session.WiFi.Get(dst); found { if station, found := mod.Session.WiFi.Get(dst); found {
station.Received += bytes station.Received += bytes
} }
src := dot11.Address2.String() src := dot11.Address2.String()
if station, found := w.Session.WiFi.Get(src); found { if station, found := mod.Session.WiFi.Get(src); found {
station.Sent += bytes station.Sent += bytes
} }
} }
} }
func (w *WiFiModule) Start() error { func (mod *WiFiModule) Start() error {
if err := w.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
w.SetRunning(true, func() { mod.SetRunning(true, func() {
// start channel hopper if needed // start channel hopper if needed
if w.channel == 0 && w.source == "" { if mod.channel == 0 && mod.source == "" {
go w.channelHopper() go mod.channelHopper()
} }
// start the pruner // start the pruner
go w.stationPruner() go mod.stationPruner()
w.reads.Add(1) mod.reads.Add(1)
defer w.reads.Done() defer mod.reads.Done()
src := gopacket.NewPacketSource(w.handle, w.handle.LinkType()) src := gopacket.NewPacketSource(mod.handle, mod.handle.LinkType())
w.pktSourceChan = src.Packets() mod.pktSourceChan = src.Packets()
for packet := range w.pktSourceChan { for packet := range mod.pktSourceChan {
if !w.Running() { if !mod.Running() {
break break
} else if packet == nil { } else if packet == nil {
continue continue
} }
w.Session.Queue.TrackPacket(uint64(len(packet.Data()))) mod.Session.Queue.TrackPacket(uint64(len(packet.Data())))
// perform initial dot11 parsing and layers validation // perform initial dot11 parsing and layers validation
if ok, radiotap, dot11 := packets.Dot11Parse(packet); ok { if ok, radiotap, dot11 := packets.Dot11Parse(packet); ok {
// check FCS checksum // check FCS checksum
if w.skipBroken && !dot11.ChecksumValid() { if mod.skipBroken && !dot11.ChecksumValid() {
w.Debug("skipping dot11 packet with invalid checksum.") mod.Debug("skipping dot11 packet with invalid checksum.")
continue continue
} }
w.discoverProbes(radiotap, dot11, packet) mod.discoverProbes(radiotap, dot11, packet)
w.discoverAccessPoints(radiotap, dot11, packet) mod.discoverAccessPoints(radiotap, dot11, packet)
w.discoverClients(radiotap, dot11, packet) mod.discoverClients(radiotap, dot11, packet)
w.discoverHandshakes(radiotap, dot11, packet) mod.discoverHandshakes(radiotap, dot11, packet)
w.updateInfo(dot11, packet) mod.updateInfo(dot11, packet)
w.updateStats(dot11, packet) mod.updateStats(dot11, packet)
} }
} }
w.pktSourceChanClosed = true mod.pktSourceChanClosed = true
}) })
return nil return nil
} }
func (w *WiFiModule) Stop() error { func (mod *WiFiModule) Stop() error {
return w.SetRunning(false, func() { return mod.SetRunning(false, func() {
// wait any pending write operation // wait any pending write operation
w.writes.Wait() mod.writes.Wait()
// signal the main for loop we want to exit // signal the main for loop we want to exit
if !w.pktSourceChanClosed { if !mod.pktSourceChanClosed {
w.pktSourceChan <- nil mod.pktSourceChan <- nil
} }
w.reads.Wait() mod.reads.Wait()
// close the pcap handle to make the main for exit // close the pcap handle to make the main for exit
w.handle.Close() mod.handle.Close()
}) })
} }

View file

@ -14,54 +14,54 @@ import (
var errNoRecon = errors.New("Module wifi.ap requires module wifi.recon to be activated.") var errNoRecon = errors.New("Module wifi.ap requires module wifi.recon to be activated.")
func (w *WiFiModule) parseApConfig() (err error) { func (mod *WiFiModule) parseApConfig() (err error) {
var bssid string var bssid string
if err, w.apConfig.SSID = w.StringParam("wifi.ap.ssid"); err != nil { if err, mod.apConfig.SSID = mod.StringParam("wifi.ap.ssid"); err != nil {
return return
} else if err, bssid = w.StringParam("wifi.ap.bssid"); err != nil { } else if err, bssid = mod.StringParam("wifi.ap.bssid"); err != nil {
return return
} else if w.apConfig.BSSID, err = net.ParseMAC(network.NormalizeMac(bssid)); err != nil { } else if mod.apConfig.BSSID, err = net.ParseMAC(network.NormalizeMac(bssid)); err != nil {
return return
} else if err, w.apConfig.Channel = w.IntParam("wifi.ap.channel"); err != nil { } else if err, mod.apConfig.Channel = mod.IntParam("wifi.ap.channel"); err != nil {
return return
} else if err, w.apConfig.Encryption = w.BoolParam("wifi.ap.encryption"); err != nil { } else if err, mod.apConfig.Encryption = mod.BoolParam("wifi.ap.encryption"); err != nil {
return return
} }
return return
} }
func (w *WiFiModule) startAp() error { func (mod *WiFiModule) startAp() error {
// we need channel hopping and packet injection for this // we need channel hopping and packet injection for this
if !w.Running() { if !mod.Running() {
return errNoRecon return errNoRecon
} else if w.apRunning { } else if mod.apRunning {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
} }
go func() { go func() {
w.apRunning = true mod.apRunning = true
defer func() { defer func() {
w.apRunning = false mod.apRunning = false
}() }()
enc := tui.Yellow("WPA2") enc := tui.Yellow("WPA2")
if !w.apConfig.Encryption { if !mod.apConfig.Encryption {
enc = tui.Green("Open") enc = tui.Green("Open")
} }
w.Info("sending beacons as SSID %s (%s) on channel %d (%s).", mod.Info("sending beacons as SSID %s (%s) on channel %d (%s).",
tui.Bold(w.apConfig.SSID), tui.Bold(mod.apConfig.SSID),
w.apConfig.BSSID.String(), mod.apConfig.BSSID.String(),
w.apConfig.Channel, mod.apConfig.Channel,
enc) enc)
for seqn := uint16(0); w.Running(); seqn++ { for seqn := uint16(0); mod.Running(); seqn++ {
w.writes.Add(1) mod.writes.Add(1)
defer w.writes.Done() defer mod.writes.Done()
if err, pkt := packets.NewDot11Beacon(w.apConfig, seqn); err != nil { if err, pkt := packets.NewDot11Beacon(mod.apConfig, seqn); err != nil {
w.Error("could not create beacon packet: %s", err) mod.Error("could not create beacon packet: %s", err)
} else { } else {
w.injectPacket(pkt) mod.injectPacket(pkt)
} }
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)

View file

@ -10,22 +10,22 @@ import (
"github.com/bettercap/bettercap/packets" "github.com/bettercap/bettercap/packets"
) )
func (w *WiFiModule) sendAssocPacket(ap *network.AccessPoint) { func (mod *WiFiModule) sendAssocPacket(ap *network.AccessPoint) {
if err, pkt := packets.NewDot11Auth(w.Session.Interface.HW, ap.HW, 1); err != nil { if err, pkt := packets.NewDot11Auth(mod.Session.Interface.HW, ap.HW, 1); err != nil {
w.Error("cloud not create auth packet: %s", err) mod.Error("cloud not create auth packet: %s", err)
} else { } else {
w.injectPacket(pkt) mod.injectPacket(pkt)
} }
if err, pkt := packets.NewDot11AssociationRequest(w.Session.Interface.HW, ap.HW, ap.ESSID(), 1); err != nil { if err, pkt := packets.NewDot11AssociationRequest(mod.Session.Interface.HW, ap.HW, ap.ESSID(), 1); err != nil {
w.Error("cloud not create association request packet: %s", err) mod.Error("cloud not create association request packet: %s", err)
} else { } else {
w.injectPacket(pkt) mod.injectPacket(pkt)
} }
} }
func (w *WiFiModule) skipAssoc(to net.HardwareAddr) bool { func (mod *WiFiModule) skipAssoc(to net.HardwareAddr) bool {
for _, mac := range w.assocSkip { for _, mac := range mod.assocSkip {
if bytes.Equal(to, mac) { if bytes.Equal(to, mac) {
return true return true
} }
@ -33,51 +33,51 @@ func (w *WiFiModule) skipAssoc(to net.HardwareAddr) bool {
return false return false
} }
func (w *WiFiModule) isAssocSilent() bool { func (mod *WiFiModule) isAssocSilent() bool {
if err, is := w.BoolParam("wifi.assoc.silent"); err != nil { if err, is := mod.BoolParam("wifi.assoc.silent"); err != nil {
w.Warning("%v", err) mod.Warning("%v", err)
} else { } else {
w.assocSilent = is mod.assocSilent = is
} }
return w.assocSilent return mod.assocSilent
} }
func (w *WiFiModule) doAssocOpen() bool { func (mod *WiFiModule) doAssocOpen() bool {
if err, is := w.BoolParam("wifi.assoc.open"); err != nil { if err, is := mod.BoolParam("wifi.assoc.open"); err != nil {
w.Warning("%v", err) mod.Warning("%v", err)
} else { } else {
w.assocOpen = is mod.assocOpen = is
} }
return w.assocOpen return mod.assocOpen
} }
func (w *WiFiModule) startAssoc(to net.HardwareAddr) error { func (mod *WiFiModule) startAssoc(to net.HardwareAddr) error {
// parse skip list // parse skip list
if err, assocSkip := w.StringParam("wifi.assoc.skip"); err != nil { if err, assocSkip := mod.StringParam("wifi.assoc.skip"); err != nil {
return err return err
} else if macs, err := network.ParseMACs(assocSkip); err != nil { } else if macs, err := network.ParseMACs(assocSkip); err != nil {
return err return err
} else { } else {
w.assocSkip = macs mod.assocSkip = macs
} }
// if not already running, temporarily enable the pcap handle // if not already running, temporarily enable the pcap handle
// for packet injection // for packet injection
if !w.Running() { if !mod.Running() {
if err := w.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
defer w.handle.Close() defer mod.handle.Close()
} }
toAssoc := make([]*network.AccessPoint, 0) toAssoc := make([]*network.AccessPoint, 0)
isBcast := network.IsBroadcastMac(to) isBcast := network.IsBroadcastMac(to)
for _, ap := range w.Session.WiFi.List() { for _, ap := range mod.Session.WiFi.List() {
if isBcast || bytes.Equal(ap.HW, to) { if isBcast || bytes.Equal(ap.HW, to) {
if !w.skipAssoc(ap.HW) { if !mod.skipAssoc(ap.HW) {
toAssoc = append(toAssoc, ap) toAssoc = append(toAssoc, ap)
} else { } else {
w.Debug("skipping ap:%v because skip list %v", ap, w.assocSkip) mod.Debug("skipping ap:%v because skip list %v", ap, mod.assocSkip)
} }
} }
} }
@ -90,8 +90,8 @@ func (w *WiFiModule) startAssoc(to net.HardwareAddr) error {
} }
go func() { go func() {
w.writes.Add(1) mod.writes.Add(1)
defer w.writes.Done() defer mod.writes.Done()
// since we need to change the wifi adapter channel for each // since we need to change the wifi adapter channel for each
// association request, let's sort by channel so we do the minimum // association request, let's sort by channel so we do the minimum
@ -102,19 +102,19 @@ func (w *WiFiModule) startAssoc(to net.HardwareAddr) error {
// send the association request frames // send the association request frames
for _, ap := range toAssoc { for _, ap := range toAssoc {
if w.Running() { if mod.Running() {
logger := w.Info logger := mod.Info
if w.isAssocSilent() { if mod.isAssocSilent() {
logger = w.Debug logger = mod.Debug
} }
if ap.IsOpen() && !w.doAssocOpen() { if ap.IsOpen() && !mod.doAssocOpen() {
w.Debug("skipping association for open network %s (wifi.assoc.open is false)", ap.ESSID()) mod.Debug("skipping association for open network %s (wifi.assoc.open is false)", ap.ESSID())
} else { } else {
logger("sending association request to AP %s (channel:%d encryption:%s)", ap.ESSID(), ap.Channel(), ap.Encryption) logger("sending association request to AP %s (channel:%d encryption:%s)", ap.ESSID(), ap.Channel(), ap.Encryption)
w.onChannel(ap.Channel(), func() { mod.onChannel(ap.Channel(), func() {
w.sendAssocPacket(ap) mod.sendAssocPacket(ap)
}) })
} }
} }

View file

@ -11,37 +11,37 @@ import (
"github.com/bettercap/bettercap/packets" "github.com/bettercap/bettercap/packets"
) )
func (w *WiFiModule) injectPacket(data []byte) { func (mod *WiFiModule) injectPacket(data []byte) {
if err := w.handle.WritePacketData(data); err != nil { if err := mod.handle.WritePacketData(data); err != nil {
w.Error("could not inject WiFi packet: %s", err) mod.Error("could not inject WiFi packet: %s", err)
w.Session.Queue.TrackError() mod.Session.Queue.TrackError()
} else { } else {
w.Session.Queue.TrackSent(uint64(len(data))) mod.Session.Queue.TrackSent(uint64(len(data)))
} }
// let the network card breath a little // let the network card breath a little
time.Sleep(10 * time.Millisecond) time.Sleep(10 * time.Millisecond)
} }
func (w *WiFiModule) sendDeauthPacket(ap net.HardwareAddr, client net.HardwareAddr) { func (mod *WiFiModule) sendDeauthPacket(ap net.HardwareAddr, client net.HardwareAddr) {
for seq := uint16(0); seq < 64 && w.Running(); seq++ { for seq := uint16(0); seq < 64 && mod.Running(); seq++ {
if err, pkt := packets.NewDot11Deauth(ap, client, ap, seq); err != nil { if err, pkt := packets.NewDot11Deauth(ap, client, ap, seq); err != nil {
w.Error("could not create deauth packet: %s", err) mod.Error("could not create deauth packet: %s", err)
continue continue
} else { } else {
w.injectPacket(pkt) mod.injectPacket(pkt)
} }
if err, pkt := packets.NewDot11Deauth(client, ap, ap, seq); err != nil { if err, pkt := packets.NewDot11Deauth(client, ap, ap, seq); err != nil {
w.Error("could not create deauth packet: %s", err) mod.Error("could not create deauth packet: %s", err)
continue continue
} else { } else {
w.injectPacket(pkt) mod.injectPacket(pkt)
} }
} }
} }
func (w *WiFiModule) skipDeauth(to net.HardwareAddr) bool { func (mod *WiFiModule) skipDeauth(to net.HardwareAddr) bool {
for _, mac := range w.deauthSkip { for _, mac := range mod.deauthSkip {
if bytes.Equal(to, mac) { if bytes.Equal(to, mac) {
return true return true
} }
@ -49,41 +49,41 @@ func (w *WiFiModule) skipDeauth(to net.HardwareAddr) bool {
return false return false
} }
func (w *WiFiModule) isDeauthSilent() bool { func (mod *WiFiModule) isDeauthSilent() bool {
if err, is := w.BoolParam("wifi.deauth.silent"); err != nil { if err, is := mod.BoolParam("wifi.deauth.silent"); err != nil {
w.Warning("%v", err) mod.Warning("%v", err)
} else { } else {
w.deauthSilent = is mod.deauthSilent = is
} }
return w.deauthSilent return mod.deauthSilent
} }
func (w *WiFiModule) doDeauthOpen() bool { func (mod *WiFiModule) doDeauthOpen() bool {
if err, is := w.BoolParam("wifi.deauth.open"); err != nil { if err, is := mod.BoolParam("wifi.deauth.open"); err != nil {
w.Warning("%v", err) mod.Warning("%v", err)
} else { } else {
w.deauthOpen = is mod.deauthOpen = is
} }
return w.deauthOpen return mod.deauthOpen
} }
func (w *WiFiModule) startDeauth(to net.HardwareAddr) error { func (mod *WiFiModule) startDeauth(to net.HardwareAddr) error {
// parse skip list // parse skip list
if err, deauthSkip := w.StringParam("wifi.deauth.skip"); err != nil { if err, deauthSkip := mod.StringParam("wifi.deauth.skip"); err != nil {
return err return err
} else if macs, err := network.ParseMACs(deauthSkip); err != nil { } else if macs, err := network.ParseMACs(deauthSkip); err != nil {
return err return err
} else { } else {
w.deauthSkip = macs mod.deauthSkip = macs
} }
// if not already running, temporarily enable the pcap handle // if not already running, temporarily enable the pcap handle
// for packet injection // for packet injection
if !w.Running() { if !mod.Running() {
if err := w.Configure(); err != nil { if err := mod.Configure(); err != nil {
return err return err
} }
defer w.handle.Close() defer mod.handle.Close()
} }
type flow struct { type flow struct {
@ -93,14 +93,14 @@ func (w *WiFiModule) startDeauth(to net.HardwareAddr) error {
toDeauth := make([]flow, 0) toDeauth := make([]flow, 0)
isBcast := network.IsBroadcastMac(to) isBcast := network.IsBroadcastMac(to)
for _, ap := range w.Session.WiFi.List() { for _, ap := range mod.Session.WiFi.List() {
isAP := bytes.Equal(ap.HW, to) isAP := bytes.Equal(ap.HW, to)
for _, client := range ap.Clients() { for _, client := range ap.Clients() {
if isBcast || isAP || bytes.Equal(client.HW, to) { if isBcast || isAP || bytes.Equal(client.HW, to) {
if !w.skipDeauth(ap.HW) && !w.skipDeauth(client.HW) { if !mod.skipDeauth(ap.HW) && !mod.skipDeauth(client.HW) {
toDeauth = append(toDeauth, flow{Ap: ap, Client: client}) toDeauth = append(toDeauth, flow{Ap: ap, Client: client})
} else { } else {
w.Debug("skipping ap:%v client:%v because skip list %v", ap, client, w.deauthSkip) mod.Debug("skipping ap:%v client:%v because skip list %v", ap, client, mod.deauthSkip)
} }
} }
} }
@ -114,8 +114,8 @@ func (w *WiFiModule) startDeauth(to net.HardwareAddr) error {
} }
go func() { go func() {
w.writes.Add(1) mod.writes.Add(1)
defer w.writes.Done() defer mod.writes.Done()
// since we need to change the wifi adapter channel for each // since we need to change the wifi adapter channel for each
// deauth packet, let's sort by channel so we do the minimum // deauth packet, let's sort by channel so we do the minimum
@ -128,19 +128,19 @@ func (w *WiFiModule) startDeauth(to net.HardwareAddr) error {
for _, deauth := range toDeauth { for _, deauth := range toDeauth {
client := deauth.Client client := deauth.Client
ap := deauth.Ap ap := deauth.Ap
if w.Running() { if mod.Running() {
logger := w.Info logger := mod.Info
if w.isDeauthSilent() { if mod.isDeauthSilent() {
logger = w.Debug logger = mod.Debug
} }
if ap.IsOpen() && !w.doDeauthOpen() { if ap.IsOpen() && !mod.doDeauthOpen() {
w.Debug("skipping deauth for open network %s (wifi.deauth.open is false)", ap.ESSID()) mod.Debug("skipping deauth for open network %s (wifi.deauth.open is false)", ap.ESSID())
} else { } else {
logger("deauthing client %s from AP %s (channel:%d encryption:%s)", client.String(), ap.ESSID(), ap.Channel(), ap.Encryption) logger("deauthing client %s from AP %s (channel:%d encryption:%s)", client.String(), ap.ESSID(), ap.Channel(), ap.Encryption)
w.onChannel(ap.Channel(), func() { mod.onChannel(ap.Channel(), func() {
w.sendDeauthPacket(ap.HW, client.HW) mod.sendDeauthPacket(ap.HW, client.HW)
}) })
} }
} }

View file

@ -6,12 +6,12 @@ import (
"github.com/bettercap/bettercap/network" "github.com/bettercap/bettercap/network"
) )
type WiFiClientEvent struct { type ClientEvent struct {
AP *network.AccessPoint AP *network.AccessPoint
Client *network.Station Client *network.Station
} }
type WiFiProbeEvent struct { type ProbeEvent struct {
FromAddr net.HardwareAddr FromAddr net.HardwareAddr
FromVendor string FromVendor string
FromAlias string FromAlias string
@ -19,7 +19,7 @@ type WiFiProbeEvent struct {
RSSI int8 RSSI int8
} }
type WiFiHandshakeEvent struct { type HandshakeEvent struct {
File string File string
NewPackets int NewPackets int
AP net.HardwareAddr AP net.HardwareAddr

View file

@ -6,64 +6,64 @@ import (
"github.com/bettercap/bettercap/network" "github.com/bettercap/bettercap/network"
) )
func (w *WiFiModule) onChannel(channel int, cb func()) { func (mod *WiFiModule) onChannel(channel int, cb func()) {
w.chanLock.Lock() mod.chanLock.Lock()
defer w.chanLock.Unlock() defer mod.chanLock.Unlock()
prev := w.stickChan prev := mod.stickChan
w.stickChan = channel mod.stickChan = channel
if err := network.SetInterfaceChannel(w.Session.Interface.Name(), channel); err != nil { if err := network.SetInterfaceChannel(mod.Session.Interface.Name(), channel); err != nil {
w.Warning("error while hopping to channel %d: %s", channel, err) mod.Warning("error while hopping to channel %d: %s", channel, err)
} else { } else {
w.Debug("hopped on channel %d", channel) mod.Debug("hopped on channel %d", channel)
} }
cb() cb()
w.stickChan = prev mod.stickChan = prev
} }
func (w *WiFiModule) channelHopper() { func (mod *WiFiModule) channelHopper() {
w.reads.Add(1) mod.reads.Add(1)
defer w.reads.Done() defer mod.reads.Done()
w.Info("channel hopper started.") mod.Info("channel hopper started.")
for w.Running() { for mod.Running() {
delay := w.hopPeriod delay := mod.hopPeriod
// if we have both 2.4 and 5ghz capabilities, we have // if we have both 2.4 and 5ghz capabilities, we have
// more channels, therefore we need to increase the time // more channels, therefore we need to increase the time
// we hop on each one otherwise me lose information // we hop on each one otherwise me lose information
if len(w.frequencies) > 14 { if len(mod.frequencies) > 14 {
delay = delay * 2 delay = delay * 2
} }
frequencies := w.frequencies frequencies := mod.frequencies
loopCurrentChannels: loopCurrentChannels:
for _, frequency := range frequencies { for _, frequency := range frequencies {
channel := network.Dot11Freq2Chan(frequency) channel := network.Dot11Freq2Chan(frequency)
// stick to the access point channel as long as it's selected // stick to the access point channel as long as it's selected
// or as long as we're deauthing on it // or as long as we're deauthing on it
if w.stickChan != 0 { if mod.stickChan != 0 {
channel = w.stickChan channel = mod.stickChan
} }
w.Debug("hopping on channel %d", channel) mod.Debug("hopping on channel %d", channel)
w.chanLock.Lock() mod.chanLock.Lock()
if err := network.SetInterfaceChannel(w.Session.Interface.Name(), channel); err != nil { if err := network.SetInterfaceChannel(mod.Session.Interface.Name(), channel); err != nil {
w.Warning("error while hopping to channel %d: %s", channel, err) mod.Warning("error while hopping to channel %d: %s", channel, err)
} }
w.chanLock.Unlock() mod.chanLock.Unlock()
select { select {
case _ = <-w.hopChanges: case _ = <-mod.hopChanges:
w.Debug("hop changed") mod.Debug("hop changed")
break loopCurrentChannels break loopCurrentChannels
case <-time.After(delay): case <-time.After(delay):
if !w.Running() { if !mod.Running() {
return return
} }
} }

View file

@ -13,28 +13,28 @@ import (
var maxStationTTL = 5 * time.Minute var maxStationTTL = 5 * time.Minute
func (w *WiFiModule) stationPruner() { func (mod *WiFiModule) stationPruner() {
w.reads.Add(1) mod.reads.Add(1)
defer w.reads.Done() defer mod.reads.Done()
w.Debug("wifi stations pruner started.") mod.Debug("wifi stations pruner started.")
for w.Running() { for mod.Running() {
// loop every AP // loop every AP
for _, ap := range w.Session.WiFi.List() { for _, ap := range mod.Session.WiFi.List() {
sinceLastSeen := time.Since(ap.LastSeen) sinceLastSeen := time.Since(ap.LastSeen)
if sinceLastSeen > maxStationTTL { if sinceLastSeen > maxStationTTL {
w.Debug("station %s not seen in %s, removing.", ap.BSSID(), sinceLastSeen) mod.Debug("station %s not seen in %s, removing.", ap.BSSID(), sinceLastSeen)
w.Session.WiFi.Remove(ap.BSSID()) mod.Session.WiFi.Remove(ap.BSSID())
continue continue
} }
// loop every AP client // loop every AP client
for _, c := range ap.Clients() { for _, c := range ap.Clients() {
sinceLastSeen := time.Since(c.LastSeen) sinceLastSeen := time.Since(c.LastSeen)
if sinceLastSeen > maxStationTTL { if sinceLastSeen > maxStationTTL {
w.Debug("client %s of station %s not seen in %s, removing.", c.String(), ap.BSSID(), sinceLastSeen) mod.Debug("client %s of station %s not seen in %s, removing.", c.String(), ap.BSSID(), sinceLastSeen)
ap.RemoveClient(c.BSSID()) ap.RemoveClient(c.BSSID())
w.Session.Events.Add("wifi.client.lost", WiFiClientEvent{ mod.Session.Events.Add("wifi.client.lost", ClientEvent{
AP: ap, AP: ap,
Client: c, Client: c,
}) })
@ -45,18 +45,18 @@ func (w *WiFiModule) stationPruner() {
} }
} }
func (w *WiFiModule) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) { func (mod *WiFiModule) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
// search for Dot11InformationElementIDSSID // search for Dot11InformationElementIDSSID
if ok, ssid := packets.Dot11ParseIDSSID(packet); ok { if ok, ssid := packets.Dot11ParseIDSSID(packet); ok {
from := dot11.Address3 from := dot11.Address3
// skip stuff we're sending // skip stuff we're sending
if w.apRunning && bytes.Equal(from, w.apConfig.BSSID) { if mod.apRunning && bytes.Equal(from, mod.apConfig.BSSID) {
return return
} }
if !network.IsZeroMac(from) && !network.IsBroadcastMac(from) { if !network.IsZeroMac(from) && !network.IsBroadcastMac(from) {
if int(radiotap.DBMAntennaSignal) >= w.minRSSI { if int(radiotap.DBMAntennaSignal) >= mod.minRSSI {
var frequency int var frequency int
bssid := from.String() bssid := from.String()
@ -66,19 +66,19 @@ func (w *WiFiModule) discoverAccessPoints(radiotap *layers.RadioTap, dot11 *laye
frequency = int(radiotap.ChannelFrequency) frequency = int(radiotap.ChannelFrequency)
} }
if ap, isNew := w.Session.WiFi.AddIfNew(ssid, bssid, frequency, radiotap.DBMAntennaSignal); !isNew { if ap, isNew := mod.Session.WiFi.AddIfNew(ssid, bssid, frequency, radiotap.DBMAntennaSignal); !isNew {
ap.EachClient(func(mac string, station *network.Station) { ap.EachClient(func(mac string, station *network.Station) {
station.Handshake.SetBeacon(packet) station.Handshake.SetBeacon(packet)
}) })
} }
} else { } else {
w.Debug("skipping %s with %d dBm", from.String(), radiotap.DBMAntennaSignal) mod.Debug("skipping %s with %d dBm", from.String(), radiotap.DBMAntennaSignal)
} }
} }
} }
} }
func (w *WiFiModule) discoverProbes(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) { func (mod *WiFiModule) discoverProbes(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
if dot11.Type != layers.Dot11TypeMgmtProbeReq { if dot11.Type != layers.Dot11TypeMgmtProbeReq {
return return
} }
@ -107,17 +107,17 @@ func (w *WiFiModule) discoverProbes(radiotap *layers.RadioTap, dot11 *layers.Dot
return return
} }
w.Session.Events.Add("wifi.client.probe", WiFiProbeEvent{ mod.Session.Events.Add("wifi.client.probe", ProbeEvent{
FromAddr: dot11.Address2, FromAddr: dot11.Address2,
FromVendor: network.ManufLookup(dot11.Address2.String()), FromVendor: network.ManufLookup(dot11.Address2.String()),
FromAlias: w.Session.Lan.GetAlias(dot11.Address2.String()), FromAlias: mod.Session.Lan.GetAlias(dot11.Address2.String()),
SSID: string(req.Contents[2 : 2+size]), SSID: string(req.Contents[2 : 2+size]),
RSSI: radiotap.DBMAntennaSignal, RSSI: radiotap.DBMAntennaSignal,
}) })
} }
func (w *WiFiModule) discoverClients(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) { func (mod *WiFiModule) discoverClients(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
w.Session.WiFi.EachAccessPoint(func(bssid string, ap *network.AccessPoint) { mod.Session.WiFi.EachAccessPoint(func(bssid string, ap *network.AccessPoint) {
// packet going to this specific BSSID? // packet going to this specific BSSID?
if packets.Dot11IsDataFor(dot11, ap.HW) { if packets.Dot11IsDataFor(dot11, ap.HW) {
bssid := dot11.Address2.String() bssid := dot11.Address2.String()
@ -125,7 +125,7 @@ func (w *WiFiModule) discoverClients(radiotap *layers.RadioTap, dot11 *layers.Do
rssi := radiotap.DBMAntennaSignal rssi := radiotap.DBMAntennaSignal
if station, isNew := ap.AddClientIfNew(bssid, freq, rssi); isNew { if station, isNew := ap.AddClientIfNew(bssid, freq, rssi); isNew {
w.Session.Events.Add("wifi.client.new", WiFiClientEvent{ mod.Session.Events.Add("wifi.client.new", ClientEvent{
AP: ap, AP: ap,
Client: station, Client: station,
}) })
@ -143,12 +143,12 @@ func allZeros(s []byte) bool {
return true return true
} }
func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) { func (mod *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers.Dot11, packet gopacket.Packet) {
if ok, key, apMac, staMac := packets.Dot11ParseEAPOL(packet, dot11); ok { if ok, key, apMac, staMac := packets.Dot11ParseEAPOL(packet, dot11); ok {
// first, locate the AP in our list by its BSSID // first, locate the AP in our list by its BSSID
ap, found := w.Session.WiFi.Get(apMac.String()) ap, found := mod.Session.WiFi.Get(apMac.String())
if !found { if !found {
w.Warning("could not find AP with BSSID %s", apMac.String()) mod.Warning("could not find AP with BSSID %s", apMac.String())
return return
} }
@ -158,7 +158,7 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers
// (Reference about PMKID https://hashcat.net/forum/thread-7717.html) // (Reference about PMKID https://hashcat.net/forum/thread-7717.html)
// In this case, we need to add ourselves as a client station of the AP // In this case, we need to add ourselves as a client station of the AP
// in order to have a consistent association of AP, client and handshakes. // in order to have a consistent association of AP, client and handshakes.
staIsUs := bytes.Equal(staMac, w.Session.Interface.HW) staIsUs := bytes.Equal(staMac, mod.Session.Interface.HW)
station, found := ap.Get(staMac.String()) station, found := ap.Get(staMac.String())
if !found { if !found {
station, _ = ap.AddClientIfNew(staMac.String(), ap.Frequency, ap.RSSI) station, _ = ap.AddClientIfNew(staMac.String(), ap.Frequency, ap.RSSI)
@ -173,7 +173,7 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers
PMKID = "with PMKID" PMKID = "with PMKID"
} }
w.Debug("got frame 1/4 of the %s <-> %s handshake (%s) (anonce:%x)", mod.Debug("got frame 1/4 of the %s <-> %s handshake (%s) (anonce:%x)",
apMac, apMac,
staMac, staMac,
PMKID, PMKID,
@ -182,7 +182,7 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers
// [2] (MIC) client is sending SNonce+MIC to the API // [2] (MIC) client is sending SNonce+MIC to the API
station.Handshake.AddFrame(1, packet) station.Handshake.AddFrame(1, packet)
w.Debug("got frame 2/4 of the %s <-> %s handshake (snonce:%x mic:%x)", mod.Debug("got frame 2/4 of the %s <-> %s handshake (snonce:%x mic:%x)",
apMac, apMac,
staMac, staMac,
key.Nonce, key.Nonce,
@ -191,7 +191,7 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers
// [3]: (INSTALL+ACK+MIC) AP informs the client that the PTK is installed // [3]: (INSTALL+ACK+MIC) AP informs the client that the PTK is installed
station.Handshake.AddFrame(2, packet) station.Handshake.AddFrame(2, packet)
w.Debug("got frame 3/4 of the %s <-> %s handshake (mic:%x)", mod.Debug("got frame 3/4 of the %s <-> %s handshake (mic:%x)",
apMac, apMac,
staMac, staMac,
key.MIC) key.MIC)
@ -200,18 +200,18 @@ func (w *WiFiModule) discoverHandshakes(radiotap *layers.RadioTap, dot11 *layers
// if we have unsaved packets as part of the handshake, save them. // if we have unsaved packets as part of the handshake, save them.
numUnsaved := station.Handshake.NumUnsaved() numUnsaved := station.Handshake.NumUnsaved()
doSave := numUnsaved > 0 doSave := numUnsaved > 0
if doSave && w.shakesFile != "" { if doSave && mod.shakesFile != "" {
w.Debug("saving handshake frames to %s", w.shakesFile) mod.Debug("saving handshake frames to %s", mod.shakesFile)
if err := w.Session.WiFi.SaveHandshakesTo(w.shakesFile, w.handle.LinkType()); err != nil { if err := mod.Session.WiFi.SaveHandshakesTo(mod.shakesFile, mod.handle.LinkType()); err != nil {
w.Error("error while saving handshake frames to %s: %s", w.shakesFile, err) mod.Error("error while saving handshake frames to %s: %s", mod.shakesFile, err)
} }
} }
// if we had unsaved packets and either the handshake is complete // if we had unsaved packets and either the handshake is complete
// or it contains the PMKID, generate a new event. // or it contains the PMKID, generate a new event.
if doSave && (rawPMKID != nil || station.Handshake.Complete()) { if doSave && (rawPMKID != nil || station.Handshake.Complete()) {
w.Session.Events.Add("wifi.client.handshake", WiFiHandshakeEvent{ mod.Session.Events.Add("wifi.client.handshake", HandshakeEvent{
File: w.shakesFile, File: mod.shakesFile,
NewPackets: numUnsaved, NewPackets: numUnsaved,
AP: apMac, AP: apMac,
Station: staMac, Station: staMac,

View file

@ -8,7 +8,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/bettercap/bettercap/modules/discovery" "github.com/bettercap/bettercap/modules/net_recon"
"github.com/bettercap/bettercap/network" "github.com/bettercap/bettercap/network"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
@ -17,11 +17,11 @@ import (
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )
func (w *WiFiModule) isApSelected() bool { func (mod *WiFiModule) isApSelected() bool {
return w.ap != nil return mod.ap != nil
} }
func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) { func (mod *WiFiModule) getRow(station *network.Station) ([]string, bool) {
// ref. https://www.metageek.com/training/resources/understanding-rssi-2.html // ref. https://www.metageek.com/training/resources/understanding-rssi-2.html
rssi := fmt.Sprintf("%d dBm", station.RSSI) rssi := fmt.Sprintf("%d dBm", station.RSSI)
if station.RSSI >= -67 { if station.RSSI >= -67 {
@ -35,19 +35,19 @@ func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) {
} }
bssid := station.HwAddress bssid := station.HwAddress
sinceStarted := time.Since(w.Session.StartedAt) sinceStarted := time.Since(mod.Session.StartedAt)
sinceFirstSeen := time.Since(station.FirstSeen) sinceFirstSeen := time.Since(station.FirstSeen)
if sinceStarted > (discovery.JustJoinedTimeInterval*2) && sinceFirstSeen <= discovery.JustJoinedTimeInterval { if sinceStarted > (net_recon.JustJoinedTimeInterval*2) && sinceFirstSeen <= net_recon.JustJoinedTimeInterval {
// if endpoint was first seen in the last 10 seconds // if endpoint was first seen in the last 10 seconds
bssid = tui.Bold(bssid) bssid = tui.Bold(bssid)
} }
seen := station.LastSeen.Format("15:04:05") seen := station.LastSeen.Format("15:04:05")
sinceLastSeen := time.Since(station.LastSeen) sinceLastSeen := time.Since(station.LastSeen)
if sinceStarted > discovery.AliveTimeInterval && sinceLastSeen <= discovery.AliveTimeInterval { if sinceStarted > net_recon.AliveTimeInterval && sinceLastSeen <= net_recon.AliveTimeInterval {
// if endpoint seen in the last 10 seconds // if endpoint seen in the last 10 seconds
seen = tui.Bold(seen) seen = tui.Bold(seen)
} else if sinceLastSeen > discovery.PresentTimeInterval { } else if sinceLastSeen > net_recon.PresentTimeInterval {
// if endpoint not seen in the last 60 seconds // if endpoint not seen in the last 60 seconds
seen = tui.Dim(seen) seen = tui.Dim(seen)
} }
@ -67,7 +67,7 @@ func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) {
// this is ugly, but necessary in order to have this // this is ugly, but necessary in order to have this
// method handle both access point and clients // method handle both access point and clients
// transparently // transparently
if ap, found := w.Session.WiFi.Get(station.HwAddress); found && (ap.HasHandshakes() || ap.HasPMKID()) { if ap, found := mod.Session.WiFi.Get(station.HwAddress); found && (ap.HasHandshakes() || ap.HasPMKID()) {
encryption = tui.Red(encryption) encryption = tui.Red(encryption)
} }
} }
@ -76,8 +76,8 @@ func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) {
recvd := ops.Ternary(station.Received > 0, humanize.Bytes(station.Received), "").(string) recvd := ops.Ternary(station.Received > 0, humanize.Bytes(station.Received), "").(string)
include := false include := false
if w.source == "" { if mod.source == "" {
for _, frequencies := range w.frequencies { for _, frequencies := range mod.frequencies {
if frequencies == station.Frequency { if frequencies == station.Frequency {
include = true include = true
break break
@ -87,11 +87,11 @@ func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) {
include = true include = true
} }
if int(station.RSSI) < w.minRSSI { if int(station.RSSI) < mod.minRSSI {
include = false include = false
} }
if w.isApSelected() { if mod.isApSelected() {
return []string{ return []string{
rssi, rssi,
bssid, bssid,
@ -105,7 +105,7 @@ func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) {
// method handle both access point and clients // method handle both access point and clients
// transparently // transparently
clients := "" clients := ""
if ap, found := w.Session.WiFi.Get(station.HwAddress); found { if ap, found := mod.Session.WiFi.Get(station.HwAddress); found {
if ap.NumClients() > 0 { if ap.NumClients() > 0 {
clients = strconv.Itoa(ap.NumClients()) clients = strconv.Itoa(ap.NumClients())
} }
@ -143,43 +143,43 @@ func (w *WiFiModule) getRow(station *network.Station) ([]string, bool) {
} }
} }
func (w *WiFiModule) doFilter(station *network.Station) bool { func (mod *WiFiModule) doFilter(station *network.Station) bool {
if w.selector.Expression == nil { if mod.selector.Expression == nil {
return true return true
} }
return w.selector.Expression.MatchString(station.BSSID()) || return mod.selector.Expression.MatchString(station.BSSID()) ||
w.selector.Expression.MatchString(station.ESSID()) || mod.selector.Expression.MatchString(station.ESSID()) ||
w.selector.Expression.MatchString(station.Alias) || mod.selector.Expression.MatchString(station.Alias) ||
w.selector.Expression.MatchString(station.Vendor) || mod.selector.Expression.MatchString(station.Vendor) ||
w.selector.Expression.MatchString(station.Encryption) mod.selector.Expression.MatchString(station.Encryption)
} }
func (w *WiFiModule) doSelection() (err error, stations []*network.Station) { func (mod *WiFiModule) doSelection() (err error, stations []*network.Station) {
if err = w.selector.Update(); err != nil { if err = mod.selector.Update(); err != nil {
return return
} }
apSelected := w.isApSelected() apSelected := mod.isApSelected()
if apSelected { if apSelected {
if ap, found := w.Session.WiFi.Get(w.ap.HwAddress); found { if ap, found := mod.Session.WiFi.Get(mod.ap.HwAddress); found {
stations = ap.Clients() stations = ap.Clients()
} else { } else {
err = fmt.Errorf("Could not find station %s", w.ap.HwAddress) err = fmt.Errorf("Could not find station %s", mod.ap.HwAddress)
return return
} }
} else { } else {
stations = w.Session.WiFi.Stations() stations = mod.Session.WiFi.Stations()
} }
filtered := []*network.Station{} filtered := []*network.Station{}
for _, station := range stations { for _, station := range stations {
if w.doFilter(station) { if mod.doFilter(station) {
filtered = append(filtered, station) filtered = append(filtered, station)
} }
} }
stations = filtered stations = filtered
switch w.selector.SortField { switch mod.selector.SortField {
case "seen": case "seen":
sort.Sort(ByWiFiSeenSorter(stations)) sort.Sort(ByWiFiSeenSorter(stations))
case "essid": case "essid":
@ -203,7 +203,7 @@ func (w *WiFiModule) doSelection() (err error, stations []*network.Station) {
} }
// default is asc // default is asc
if w.selector.Sort == "desc" { if mod.selector.Sort == "desc" {
// from https://github.com/golang/go/wiki/SliceTricks // from https://github.com/golang/go/wiki/SliceTricks
for i := len(stations)/2 - 1; i >= 0; i-- { for i := len(stations)/2 - 1; i >= 0; i-- {
opp := len(stations) - 1 - i opp := len(stations) - 1 - i
@ -211,8 +211,8 @@ func (w *WiFiModule) doSelection() (err error, stations []*network.Station) {
} }
} }
if w.selector.Limit > 0 { if mod.selector.Limit > 0 {
limit := w.selector.Limit limit := mod.selector.Limit
max := len(stations) max := len(stations)
if limit > max { if limit > max {
limit = max limit = max
@ -223,7 +223,7 @@ func (w *WiFiModule) doSelection() (err error, stations []*network.Station) {
return return
} }
func (w *WiFiModule) colDecorate(colNames []string, name string, dir string) { func (mod *WiFiModule) colDecorate(colNames []string, name string, dir string) {
for i, c := range colNames { for i, c := range colNames {
if c == name { if c == name {
colNames[i] += " " + dir colNames[i] += " " + dir
@ -232,101 +232,101 @@ func (w *WiFiModule) colDecorate(colNames []string, name string, dir string) {
} }
} }
func (w *WiFiModule) colNames(nrows int) []string { func (mod *WiFiModule) colNames(nrows int) []string {
columns := []string(nil) columns := []string(nil)
if !w.isApSelected() { if !mod.isApSelected() {
columns = []string{"RSSI", "BSSID", "SSID", "Encryption", "WPS", "Ch", "Clients", "Sent", "Recvd", "Seen"} columns = []string{"RSSI", "BSSID", "SSID", "Encryption", "WPS", "Ch", "Clients", "Sent", "Recvd", "Seen"}
} else if nrows > 0 { } else if nrows > 0 {
columns = []string{"RSSI", "BSSID", "Ch", "Sent", "Recvd", "Seen"} columns = []string{"RSSI", "BSSID", "Ch", "Sent", "Recvd", "Seen"}
fmt.Printf("\n%s clients:\n", w.ap.HwAddress) fmt.Printf("\n%s clients:\n", mod.ap.HwAddress)
} else { } else {
fmt.Printf("\nNo authenticated clients detected for %s.\n", w.ap.HwAddress) fmt.Printf("\nNo authenticated clients detected for %s.\n", mod.ap.HwAddress)
} }
if columns != nil { if columns != nil {
switch w.selector.SortField { switch mod.selector.SortField {
case "seen": case "seen":
w.colDecorate(columns, "Seen", w.selector.SortSymbol) mod.colDecorate(columns, "Seen", mod.selector.SortSymbol)
case "essid": case "essid":
w.colDecorate(columns, "SSID", w.selector.SortSymbol) mod.colDecorate(columns, "SSID", mod.selector.SortSymbol)
case "bssid": case "bssid":
w.colDecorate(columns, "BSSID", w.selector.SortSymbol) mod.colDecorate(columns, "BSSID", mod.selector.SortSymbol)
case "channel": case "channel":
w.colDecorate(columns, "Ch", w.selector.SortSymbol) mod.colDecorate(columns, "Ch", mod.selector.SortSymbol)
case "clients": case "clients":
w.colDecorate(columns, "Clients", w.selector.SortSymbol) mod.colDecorate(columns, "Clients", mod.selector.SortSymbol)
case "encryption": case "encryption":
w.colDecorate(columns, "Encryption", w.selector.SortSymbol) mod.colDecorate(columns, "Encryption", mod.selector.SortSymbol)
case "sent": case "sent":
w.colDecorate(columns, "Sent", w.selector.SortSymbol) mod.colDecorate(columns, "Sent", mod.selector.SortSymbol)
case "rcvd": case "rcvd":
w.colDecorate(columns, "Recvd", w.selector.SortSymbol) mod.colDecorate(columns, "Recvd", mod.selector.SortSymbol)
case "rssi": case "rssi":
w.colDecorate(columns, "RSSI", w.selector.SortSymbol) mod.colDecorate(columns, "RSSI", mod.selector.SortSymbol)
} }
} }
return columns return columns
} }
func (w *WiFiModule) showStatusBar() { func (mod *WiFiModule) showStatusBar() {
w.Session.Queue.Stats.RLock() mod.Session.Queue.Stats.RLock()
defer w.Session.Queue.Stats.RUnlock() defer mod.Session.Queue.Stats.RUnlock()
parts := []string{ parts := []string{
fmt.Sprintf("%s (ch. %d)", w.Session.Interface.Name(), network.GetInterfaceChannel(w.Session.Interface.Name())), fmt.Sprintf("%s (ch. %d)", mod.Session.Interface.Name(), network.GetInterfaceChannel(mod.Session.Interface.Name())),
fmt.Sprintf("%s %s", tui.Red("↑"), humanize.Bytes(w.Session.Queue.Stats.Sent)), fmt.Sprintf("%s %s", tui.Red("↑"), humanize.Bytes(mod.Session.Queue.Stats.Sent)),
fmt.Sprintf("%s %s", tui.Green("↓"), humanize.Bytes(w.Session.Queue.Stats.Received)), fmt.Sprintf("%s %s", tui.Green("↓"), humanize.Bytes(mod.Session.Queue.Stats.Received)),
fmt.Sprintf("%d pkts", w.Session.Queue.Stats.PktReceived), fmt.Sprintf("%d pkts", mod.Session.Queue.Stats.PktReceived),
} }
if nErrors := w.Session.Queue.Stats.Errors; nErrors > 0 { if nErrors := mod.Session.Queue.Stats.Errors; nErrors > 0 {
parts = append(parts, fmt.Sprintf("%d errs", nErrors)) parts = append(parts, fmt.Sprintf("%d errs", nErrors))
} }
if nHandshakes := w.Session.WiFi.NumHandshakes(); nHandshakes > 0 { if nHandshakes := mod.Session.WiFi.NumHandshakes(); nHandshakes > 0 {
parts = append(parts, fmt.Sprintf("%d handshakes", nHandshakes)) parts = append(parts, fmt.Sprintf("%d handshakes", nHandshakes))
} }
fmt.Printf("\n%s\n\n", strings.Join(parts, " / ")) fmt.Printf("\n%s\n\n", strings.Join(parts, " / "))
} }
func (w *WiFiModule) Show() (err error) { func (mod *WiFiModule) Show() (err error) {
var stations []*network.Station var stations []*network.Station
if err, stations = w.doSelection(); err != nil { if err, stations = mod.doSelection(); err != nil {
return return
} }
rows := make([][]string, 0) rows := make([][]string, 0)
for _, s := range stations { for _, s := range stations {
if row, include := w.getRow(s); include { if row, include := mod.getRow(s); include {
rows = append(rows, row) rows = append(rows, row)
} }
} }
nrows := len(rows) nrows := len(rows)
if nrows > 0 { if nrows > 0 {
tui.Table(os.Stdout, w.colNames(nrows), rows) tui.Table(os.Stdout, mod.colNames(nrows), rows)
} }
w.showStatusBar() mod.showStatusBar()
w.Session.Refresh() mod.Session.Refresh()
return nil return nil
} }
func (w *WiFiModule) ShowWPS(bssid string) (err error) { func (mod *WiFiModule) ShowWPS(bssid string) (err error) {
toShow := []*network.Station{} toShow := []*network.Station{}
if bssid == network.BroadcastMac { if bssid == network.BroadcastMac {
for _, station := range w.Session.WiFi.List() { for _, station := range mod.Session.WiFi.List() {
if station.HasWPS() { if station.HasWPS() {
toShow = append(toShow, station.Station) toShow = append(toShow, station.Station)
} }
} }
} else { } else {
if station, found := w.Session.WiFi.Get(bssid); found { if station, found := mod.Session.WiFi.Get(bssid); found {
if station.HasWPS() { if station.HasWPS() {
toShow = append(toShow, station.Station) toShow = append(toShow, station.Station)
} }

View file

@ -23,31 +23,31 @@ type WOL struct {
} }
func NewWOL(s *session.Session) *WOL { func NewWOL(s *session.Session) *WOL {
w := &WOL{ mod := &WOL{
SessionModule: session.NewSessionModule("wol", s), SessionModule: session.NewSessionModule("wol", s),
} }
w.AddHandler(session.NewModuleHandler("wol.eth MAC", "wol.eth(\\s.+)?", mod.AddHandler(session.NewModuleHandler("wol.eth MAC", "wol.eth(\\s.+)?",
"Send a WOL as a raw ethernet packet of type 0x0847 (if no MAC is specified, ff:ff:ff:ff:ff:ff will be used).", "Send a WOL as a raw ethernet packet of type 0x0847 (if no MAC is specified, ff:ff:ff:ff:ff:ff will be used).",
func(args []string) error { func(args []string) error {
if mac, err := parseMAC(args); err != nil { if mac, err := parseMAC(args); err != nil {
return err return err
} else { } else {
return w.wolETH(mac) return mod.wolETH(mac)
} }
})) }))
w.AddHandler(session.NewModuleHandler("wol.udp MAC", "wol.udp(\\s.+)?", mod.AddHandler(session.NewModuleHandler("wol.udp MAC", "wol.udp(\\s.+)?",
"Send a WOL as an IPv4 broadcast packet to UDP port 9 (if no MAC is specified, ff:ff:ff:ff:ff:ff will be used).", "Send a WOL as an IPv4 broadcast packet to UDP port 9 (if no MAC is specified, ff:ff:ff:ff:ff:ff will be used).",
func(args []string) error { func(args []string) error {
if mac, err := parseMAC(args); err != nil { if mac, err := parseMAC(args); err != nil {
return err return err
} else { } else {
return w.wolUDP(mac) return mod.wolUDP(mac)
} }
})) }))
return w return mod
} }
func parseMAC(args []string) (string, error) { func parseMAC(args []string) (string, error) {
@ -66,27 +66,27 @@ func parseMAC(args []string) (string, error) {
return mac, nil return mac, nil
} }
func (w *WOL) Name() string { func (mod *WOL) Name() string {
return "wol" return "wol"
} }
func (w *WOL) Description() string { func (mod *WOL) Description() string {
return "A module to send Wake On LAN packets in broadcast or to a specific MAC." return "A module to send Wake On LAN packets in broadcast or to a specific MAC."
} }
func (w *WOL) Author() string { func (mod *WOL) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>" return "Simone Margaritelli <evilsocket@gmail.com>"
} }
func (w *WOL) Configure() error { func (mod *WOL) Configure() error {
return nil return nil
} }
func (w *WOL) Start() error { func (mod *WOL) Start() error {
return nil return nil
} }
func (w *WOL) Stop() error { func (mod *WOL) Stop() error {
return nil return nil
} }
@ -99,14 +99,14 @@ func buildPayload(mac string) []byte {
return payload return payload
} }
func (w *WOL) wolETH(mac string) error { func (mod *WOL) wolETH(mac string) error {
w.SetRunning(true, nil) mod.SetRunning(true, nil)
defer w.SetRunning(false, nil) defer mod.SetRunning(false, nil)
payload := buildPayload(mac) payload := buildPayload(mac)
w.Info("sending %d bytes of ethernet WOL packet to %s", len(payload), tui.Bold(mac)) mod.Info("sending %d bytes of ethernet WOL packet to %s", len(payload), tui.Bold(mac))
eth := layers.Ethernet{ eth := layers.Ethernet{
SrcMAC: w.Session.Interface.HW, SrcMAC: mod.Session.Interface.HW,
DstMAC: layers.EthernetBroadcast, DstMAC: layers.EthernetBroadcast,
EthernetType: 0x0842, EthernetType: 0x0842,
} }
@ -117,18 +117,18 @@ func (w *WOL) wolETH(mac string) error {
} }
raw = append(raw, payload...) raw = append(raw, payload...)
return w.Session.Queue.Send(raw) return mod.Session.Queue.Send(raw)
} }
func (w *WOL) wolUDP(mac string) error { func (mod *WOL) wolUDP(mac string) error {
w.SetRunning(true, nil) mod.SetRunning(true, nil)
defer w.SetRunning(false, nil) defer mod.SetRunning(false, nil)
payload := buildPayload(mac) payload := buildPayload(mac)
w.Info("sending %d bytes of UDP WOL packet to %s", len(payload), tui.Bold(mac)) mod.Info("sending %d bytes of UDP WOL packet to %s", len(payload), tui.Bold(mac))
eth := layers.Ethernet{ eth := layers.Ethernet{
SrcMAC: w.Session.Interface.HW, SrcMAC: mod.Session.Interface.HW,
DstMAC: layers.EthernetBroadcast, DstMAC: layers.EthernetBroadcast,
EthernetType: layers.EthernetTypeIPv4, EthernetType: layers.EthernetTypeIPv4,
} }
@ -137,7 +137,7 @@ func (w *WOL) wolUDP(mac string) error {
Protocol: layers.IPProtocolUDP, Protocol: layers.IPProtocolUDP,
Version: 4, Version: 4,
TTL: 64, TTL: 64,
SrcIP: w.Session.Interface.IP, SrcIP: mod.Session.Interface.IP,
DstIP: net.ParseIP("255.255.255.255"), DstIP: net.ParseIP("255.255.255.255"),
} }
@ -154,5 +154,5 @@ func (w *WOL) wolUDP(mac string) error {
} }
raw = append(raw, payload...) raw = append(raw, payload...)
return w.Session.Queue.Send(raw) return mod.Session.Queue.Send(raw)
} }