mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
new: implemented can.dup and can.dump.inject to read a candump log file
This commit is contained in:
parent
840f819484
commit
7702207ee9
4 changed files with 108 additions and 14 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -15,3 +15,4 @@ stage/
|
||||||
/snap
|
/snap
|
||||||
.idea
|
.idea
|
||||||
/cover.out
|
/cover.out
|
||||||
|
/can-data
|
|
@ -2,6 +2,7 @@ package can
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/v2/session"
|
"github.com/bettercap/bettercap/v2/session"
|
||||||
|
@ -13,6 +14,8 @@ type CANModule struct {
|
||||||
session.SessionModule
|
session.SessionModule
|
||||||
|
|
||||||
deviceName string
|
deviceName string
|
||||||
|
dumpName string
|
||||||
|
dumpInject bool
|
||||||
transport string
|
transport string
|
||||||
filter string
|
filter string
|
||||||
filterExpr *bexpr.Evaluator
|
filterExpr *bexpr.Evaluator
|
||||||
|
@ -30,6 +33,8 @@ func NewCanModule(s *session.Session) *CANModule {
|
||||||
filterExpr: nil,
|
filterExpr: nil,
|
||||||
transport: "can",
|
transport: "can",
|
||||||
deviceName: "can0",
|
deviceName: "can0",
|
||||||
|
dumpName: "",
|
||||||
|
dumpInject: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.AddParam(session.NewStringParameter("can.device",
|
mod.AddParam(session.NewStringParameter("can.device",
|
||||||
|
@ -37,6 +42,15 @@ func NewCanModule(s *session.Session) *CANModule {
|
||||||
"",
|
"",
|
||||||
"CAN-bus device."))
|
"CAN-bus device."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewStringParameter("can.dump",
|
||||||
|
mod.dumpName,
|
||||||
|
"",
|
||||||
|
"Load CAN traffic from this candump log file."))
|
||||||
|
|
||||||
|
mod.AddParam(session.NewBoolParameter("can.dump.inject",
|
||||||
|
fmt.Sprintf("%v", mod.dumpInject),
|
||||||
|
"Write CAN traffic read form the candump log file to the selected can.device."))
|
||||||
|
|
||||||
mod.AddParam(session.NewStringParameter("can.transport",
|
mod.AddParam(session.NewStringParameter("can.transport",
|
||||||
mod.transport,
|
mod.transport,
|
||||||
"",
|
"",
|
||||||
|
@ -53,18 +67,6 @@ func NewCanModule(s *session.Session) *CANModule {
|
||||||
return mod.Start()
|
return mod.Start()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("can.load_dbc PATH", "",
|
|
||||||
"Start CAN-bus discovery.",
|
|
||||||
func(args []string) error {
|
|
||||||
return mod.Start()
|
|
||||||
}))
|
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("can.dbc.load NAME", "can.dbc.load (.+)",
|
|
||||||
"Load a DBC file from the list of available ones or from disk.",
|
|
||||||
func(args []string) error {
|
|
||||||
return mod.dbcLoad(args[0])
|
|
||||||
}))
|
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("can.recon off", "",
|
mod.AddHandler(session.NewModuleHandler("can.recon off", "",
|
||||||
"Stop CAN-bus discovery.",
|
"Stop CAN-bus discovery.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
|
@ -84,6 +86,12 @@ func NewCanModule(s *session.Session) *CANModule {
|
||||||
return mod.Show()
|
return mod.Show()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
mod.AddHandler(session.NewModuleHandler("can.dbc.load NAME", "can.dbc.load (.+)",
|
||||||
|
"Load a DBC file from the list of available ones or from disk.",
|
||||||
|
func(args []string) error {
|
||||||
|
return mod.dbcLoad(args[0])
|
||||||
|
}))
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("can.inject FRAME_EXPRESSION", `(?i)^can\.inject\s+([a-fA-F0-9#R]+)$`,
|
mod.AddHandler(session.NewModuleHandler("can.inject FRAME_EXPRESSION", `(?i)^can\.inject\s+([a-fA-F0-9#R]+)$`,
|
||||||
"Parse FRAME_EXPRESSION as 'id#data' and inject it as a CAN frame.",
|
"Parse FRAME_EXPRESSION as 'id#data' and inject it as a CAN frame.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
|
|
76
modules/can/can_dump_reader.go
Normal file
76
modules/can/can_dump_reader.go
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
package can
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/str"
|
||||||
|
"go.einride.tech/can"
|
||||||
|
)
|
||||||
|
|
||||||
|
// (1700623093.260875) can0 7E0#0322128C00000000
|
||||||
|
var dumpLineParser = regexp.MustCompile(`(?m)^\(([\d\.]+)\)\s+([^\s]+)\s+(.+)`)
|
||||||
|
|
||||||
|
type dumpEntry struct {
|
||||||
|
Time string
|
||||||
|
Device string
|
||||||
|
Frame string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *CANModule) startDumpReader() error {
|
||||||
|
mod.Info("loading CAN dump from %s ...", mod.dumpName)
|
||||||
|
|
||||||
|
file, err := os.Open(mod.dumpName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
entries := make([]dumpEntry, 0)
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := str.Trim(scanner.Text())
|
||||||
|
if line != "" {
|
||||||
|
if m := dumpLineParser.FindStringSubmatch(line); len(m) != 4 {
|
||||||
|
mod.Warning("unexpected line: '%s' -> %d matches", line, len(m))
|
||||||
|
} else {
|
||||||
|
entries = append(entries, dumpEntry{
|
||||||
|
Time: m[1],
|
||||||
|
Device: m[2],
|
||||||
|
Frame: m[3],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = scanner.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Info("loaded %d entries from candump log", len(entries))
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
mod.Info("candump reader started ...")
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
frame := can.Frame{}
|
||||||
|
if err := frame.UnmarshalString(entry.Frame); err != nil {
|
||||||
|
mod.Error("could not unmarshal CAN frame: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if mod.dumpInject {
|
||||||
|
if err := mod.send.TransmitFrame(context.Background(), frame); err != nil {
|
||||||
|
mod.Error("could not send CAN frame: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mod.onFrame(frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -25,6 +25,10 @@ func (mod *CANModule) Configure() error {
|
||||||
return session.ErrAlreadyStarted(mod.Name())
|
return session.ErrAlreadyStarted(mod.Name())
|
||||||
} else if err, mod.deviceName = mod.StringParam("can.device"); err != nil {
|
} else if err, mod.deviceName = mod.StringParam("can.device"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else if err, mod.dumpName = mod.StringParam("can.dump"); err != nil {
|
||||||
|
return err
|
||||||
|
} else if err, mod.dumpInject = mod.BoolParam("can.dump.inject"); err != nil {
|
||||||
|
return err
|
||||||
} else if err, mod.transport = mod.StringParam("can.transport"); err != nil {
|
} else if err, mod.transport = mod.StringParam("can.transport"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if mod.transport != "can" && mod.transport != "udp" {
|
} else if mod.transport != "can" && mod.transport != "udp" {
|
||||||
|
@ -43,10 +47,15 @@ func (mod *CANModule) Configure() error {
|
||||||
if mod.conn, err = socketcan.Dial(mod.transport, mod.deviceName); err != nil {
|
if mod.conn, err = socketcan.Dial(mod.transport, mod.deviceName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.recv = socketcan.NewReceiver(mod.conn)
|
mod.recv = socketcan.NewReceiver(mod.conn)
|
||||||
mod.send = socketcan.NewTransmitter(mod.conn)
|
mod.send = socketcan.NewTransmitter(mod.conn)
|
||||||
|
|
||||||
|
if mod.dumpName != "" {
|
||||||
|
if err = mod.startDumpReader(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue