mirror of
https://github.com/bettercap/bettercap.git
synced 2024-11-08 06:30:13 -08:00
159 lines
3.3 KiB
Go
159 lines
3.3 KiB
Go
package wol
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
|
|
"github.com/bettercap/bettercap/v2/packets"
|
|
"github.com/bettercap/bettercap/v2/session"
|
|
|
|
"github.com/google/gopacket/layers"
|
|
|
|
"github.com/evilsocket/islazy/str"
|
|
"github.com/evilsocket/islazy/tui"
|
|
)
|
|
|
|
var (
|
|
reMAC = regexp.MustCompile(`^([0-9a-fA-F]{2}[:-]){5}([0-9a-fA-F]{2})$`)
|
|
)
|
|
|
|
type WOL struct {
|
|
session.SessionModule
|
|
}
|
|
|
|
func NewWOL(s *session.Session) *WOL {
|
|
mod := &WOL{
|
|
SessionModule: session.NewSessionModule("wol", 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).",
|
|
func(args []string) error {
|
|
if mac, err := parseMAC(args); err != nil {
|
|
return err
|
|
} else {
|
|
return mod.wolETH(mac)
|
|
}
|
|
}))
|
|
|
|
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).",
|
|
func(args []string) error {
|
|
if mac, err := parseMAC(args); err != nil {
|
|
return err
|
|
} else {
|
|
return mod.wolUDP(mac)
|
|
}
|
|
}))
|
|
|
|
return mod
|
|
}
|
|
|
|
func parseMAC(args []string) (string, error) {
|
|
mac := "ff:ff:ff:ff:ff:ff"
|
|
if len(args) == 1 {
|
|
tmp := str.Trim(args[0])
|
|
if tmp != "" {
|
|
if !reMAC.MatchString(tmp) {
|
|
return "", fmt.Errorf("%s is not a valid MAC address.", tmp)
|
|
} else {
|
|
mac = tmp
|
|
}
|
|
}
|
|
}
|
|
|
|
return mac, nil
|
|
}
|
|
|
|
func (mod *WOL) Name() string {
|
|
return "wol"
|
|
}
|
|
|
|
func (mod *WOL) Description() string {
|
|
return "A module to send Wake On LAN packets in broadcast or to a specific MAC."
|
|
}
|
|
|
|
func (mod *WOL) Author() string {
|
|
return "Simone Margaritelli <evilsocket@gmail.com>"
|
|
}
|
|
|
|
func (mod *WOL) Configure() error {
|
|
return nil
|
|
}
|
|
|
|
func (mod *WOL) Start() error {
|
|
return nil
|
|
}
|
|
|
|
func (mod *WOL) Stop() error {
|
|
return nil
|
|
}
|
|
|
|
func buildPayload(mac string) []byte {
|
|
raw, _ := net.ParseMAC(mac)
|
|
payload := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
|
for i := 0; i < 16; i++ {
|
|
payload = append(payload, raw...)
|
|
}
|
|
return payload
|
|
}
|
|
|
|
func (mod *WOL) wolETH(mac string) error {
|
|
mod.SetRunning(true, nil)
|
|
defer mod.SetRunning(false, nil)
|
|
|
|
payload := buildPayload(mac)
|
|
mod.Info("sending %d bytes of ethernet WOL packet to %s", len(payload), tui.Bold(mac))
|
|
eth := layers.Ethernet{
|
|
SrcMAC: mod.Session.Interface.HW,
|
|
DstMAC: layers.EthernetBroadcast,
|
|
EthernetType: 0x0842,
|
|
}
|
|
|
|
err, raw := packets.Serialize(ð)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
raw = append(raw, payload...)
|
|
return mod.Session.Queue.Send(raw)
|
|
}
|
|
|
|
func (mod *WOL) wolUDP(mac string) error {
|
|
mod.SetRunning(true, nil)
|
|
defer mod.SetRunning(false, nil)
|
|
|
|
payload := buildPayload(mac)
|
|
mod.Info("sending %d bytes of UDP WOL packet to %s", len(payload), tui.Bold(mac))
|
|
|
|
eth := layers.Ethernet{
|
|
SrcMAC: mod.Session.Interface.HW,
|
|
DstMAC: layers.EthernetBroadcast,
|
|
EthernetType: layers.EthernetTypeIPv4,
|
|
}
|
|
|
|
ip4 := layers.IPv4{
|
|
Protocol: layers.IPProtocolUDP,
|
|
Version: 4,
|
|
TTL: 64,
|
|
SrcIP: mod.Session.Interface.IP,
|
|
DstIP: net.ParseIP("255.255.255.255"),
|
|
}
|
|
|
|
udp := layers.UDP{
|
|
SrcPort: layers.UDPPort(32767),
|
|
DstPort: layers.UDPPort(9),
|
|
}
|
|
|
|
udp.SetNetworkLayerForChecksum(&ip4)
|
|
|
|
err, raw := packets.Serialize(ð, &ip4, &udp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
raw = append(raw, payload...)
|
|
return mod.Session.Queue.Send(raw)
|
|
}
|