Compare commits

..

2 Commits

Author SHA1 Message Date
Kevin F
d48ca89d20 Replace sendkeys with keylogger 2023-03-02 21:20:34 -06:00
Kevin F
75907dff43 Remove duplicate code fences 2023-01-29 20:00:44 -06:00
8 changed files with 46 additions and 50 deletions

View File

@ -14,9 +14,9 @@ When the GoSmartKeyboard client is started, it does the following:
--- handle client command --- handle client command
if len(os.Args) > 1 { if len(os.Args) > 1 {
@{get client fifo input file from environment} @{get client fifo input file from environment}
@{setup client} @{setup client}
if clientFifoInputFileExists { if clientFifoInputFileEnvExists {
@{start client with fifo} @{start client with fifo}
os.Exit(0) os.Exit(0)
} }
@ -97,6 +97,8 @@ if !strings.HasPrefix(connectionURL, "ws://") && !strings.HasPrefix(connectionUR
var inputString string var inputString string
syscall.Mkfifo(clientFifoInputFile, syscall.S_IFIFO|0666)
for { for {
input, err := ioutil.ReadFile(clientFifoInputFile) input, err := ioutil.ReadFile(clientFifoInputFile)
if err != nil { if err != nil {
@ -118,7 +120,6 @@ for {
``` ```
## Sending keys from stdin ## Sending keys from stdin
@ -187,6 +188,7 @@ package main
import ( import (
"strings" "strings"
"io/ioutil" "io/ioutil"
"syscall"
"io" "io"
"bufio" "bufio"
"log" "log"

View File

@ -24,14 +24,13 @@ We use sha3 to hash authentication tokens. It is not in the crypto standard libr
--- ---
# sendkeys # keylogger
We use keylogger to get keyboard input on the client and simulate keystrokes on the server.
In order to avoid coding key press simulation for every major platform, we use [sendkeys](https://github.com/yunginnanet/sendkeys). This is a cross-platform library that uses the OS's native key press simulation using [keybd_event](https://github.com/micmonay/keybd_event) --- keylogger import string
--- sendkeys import string "github.com/MarinX/keylogger"
"github.com/EgosOwn/sendkeys"
--- ---

View File

@ -7,7 +7,7 @@ Some users may always want xdotool, see the [Streaming.md](Streaming.md) file fo
``` go ``` go
--- always use xdotool environment variable --- always use xdotool environment variable
var alwaysUseXdotool := false var alwaysUseXdotool = false
alwaysUseXdotoolEnv, alwaysUseXdotoolExists := os.LookupEnv("KEYBOARD_ALWAYS_USE_XDOTOOL") alwaysUseXdotoolEnv, alwaysUseXdotoolExists := os.LookupEnv("KEYBOARD_ALWAYS_USE_XDOTOOL")
if alwaysUseXdotoolExists { if alwaysUseXdotoolExists {
if alwaysUseXdotoolEnv == "true" || alwaysUseXdotoolEnv == "1" { if alwaysUseXdotoolEnv == "true" || alwaysUseXdotoolEnv == "1" {
@ -46,7 +46,7 @@ authTokenInput, authTokenInputExists := os.LookupEnv("KEYBOARD_AUTH")
--- get client fifo input file from environment --- get client fifo input file from environment
clientFifoInputFile, clientFifoInputFileExists := os.LookupEnv("KEYBOARD_FIFO") clientFifoInputFile, clientFifoInputFileEnvExists := os.LookupEnv("KEYBOARD_FIFO")
--- ---

View File

@ -1,39 +1,25 @@
# Send keys streaming approach # uinput streaming approach
When applicable to use send keys, we need to detect Enter, Tab, and BackSpace and use the applicatble functions.
We test if it meets the characterRegex, and if so we iterate for each character and send the corresponding key.
Otherwise we send the entire string at once.
``` go ``` go
--- do streaming sendkeys approach --- do streaming keylogger approach
if characterRegex.MatchString(message_string) {
for _, character := range message_string { key := ""
charString := string(character) if strings.HasPrefix(message_string, "{KEYDWN}") {
if charString == "\n" { key = strings.TrimPrefix(string(message_string), "{KEYDWN}")
keyboard.Enter() k.Write(1, key)
continue } else if strings.HasPrefix(message_string, "{KEYUP}") {
} key = strings.TrimPrefix(string(message_string), "{KEYUP}")
if charString == "\t" { k.Write(0, key)
keyboard.Tab() } else{
continue for _, key := range message_string {
} // write once will simulate keyboard press/release, for long press or release, lookup at Write
if charString == "\b" { k.WriteOnce(string(key))
keyboard.BackSpace()
continue
}
err = keyboard.Type(charString)
if err != nil {
log.Println("type:", err)
}
continue
} }
continue
}
err = keyboard.Type(message_string)
if err != nil {
log.Println("type:", err)
} }
--- ---
``` ```

View File

@ -68,7 +68,7 @@ import(
"log" "log"
"keyboard.voidnet.tech/auth" "keyboard.voidnet.tech/auth"
@{gorilla/websocket import string} @{gorilla/websocket import string}
@{sendkeys import string} @{keylogger import string}
) )
var listener net.Listener var listener net.Listener

View File

@ -2,9 +2,9 @@
We use the Gorilla websocket library to handle the websocket connection. We use the Gorilla websocket library to handle the websocket connection.
Most of the time, we can use sendkeys (which uses libinput) to effeciently press keys. However, if we need to send a character that sendkeys doesn't know about, we can use the xdotool command. xdotool is also useful if one does not want to use root. Most of the time, we can use the keylogger library (which uses uinput) to effeciently press keys. However, if we need to send a character that keylogger doesn't know about, we can use the xdotool command. xdotool is also useful if one does not want to use root.
xdotool spawns a new process for each keypress, so it's not as effecient as sendkeys. xdotool spawns a new process for each keypress, so it's not as effecient as keylogger.
To specify xdotool usage, the client should send a message with the format `{kb_cmd:xdotool}:message` where message is a utf-8 string. To specify xdotool usage, the client should send a message with the format `{kb_cmd:xdotool}:message` where message is a utf-8 string.
@ -14,7 +14,20 @@ To specify xdotool usage, the client should send a message with the format `{kb_
func clientConnected(w http.ResponseWriter, r *http.Request) { func clientConnected(w http.ResponseWriter, r *http.Request) {
// regex if string has characters we need to convert to key presses // regex if string has characters we need to convert to key presses
characterRegex, _ := regexp.Compile(`[^\x08]\x08|\t|\n`) characterRegex, _ := regexp.Compile(`[^\x08]\x08|\t|\n`)
keyboard, err := sendkeys.NewKBWrapWithOptions(sendkeys.Noisy)
// find keyboard device, does not require a root permission
keyboard := keylogger.FindKeyboardDevice()
// check if we found a path to keyboard
if len(keyboard) <= 0 {
return
}
k, err := keylogger.New(keyboard)
if err != nil {
return
}
defer k.Close()
@{always use xdotool environment variable} @{always use xdotool environment variable}
@ -84,7 +97,7 @@ doXDoTool := func(command string, keys string)(err error) {
@{handle xdotoool commands} @{handle xdotoool commands}
@{do streaming sendkeys approach} @{do streaming keylogger approach}
--- ---
``` ```

View File

@ -4,10 +4,6 @@ Currently the two commands are `type` and `key`. `type` is used to type a charac
`type` is specified by '{kb_cmd:xdotool}:', and `key` is specified by '{kb_cmd:kxdotool}:'. If the command is not specified and `alwaysUseXdotool` is set from the environment variable, it will default to `type`. `type` is specified by '{kb_cmd:xdotool}:', and `key` is specified by '{kb_cmd:kxdotool}:'. If the command is not specified and `alwaysUseXdotool` is set from the environment variable, it will default to `type`.
``` go
``` go
``` go ``` go
--- handle xdotoool commands --- handle xdotoool commands

View File

@ -19,7 +19,7 @@ import (
func main(){ func main(){
var input string var input string
@{get client fifo input file from environment} @{get client input file from environment}
if ! clientFifoInputFileExists { if ! clientFifoInputFileExists {
os.Exit(1) os.Exit(1)
} }