Moved control commands to their own file
Delimit all messages to fix fifo race condition
This commit is contained in:
parent
a8574dfebe
commit
b941235007
28
Client.md
28
Client.md
@ -7,12 +7,11 @@ When the GoSmartKeyboard client is started, it does the following:
|
|||||||
3. Connect to the server.
|
3. Connect to the server.
|
||||||
4 Send the auth token to the server.
|
4 Send the auth token to the server.
|
||||||
5. If the server responds with "authenticated", we start reading keys from stdin and sending them to the server until EOF.
|
5. If the server responds with "authenticated", we start reading keys from stdin and sending them to the server until EOF.
|
||||||
6. If KEYBOARD_FIFO is specified as an environment variable, we read from the path specified there instead as a named pipe.
|
5.1 If the environment variable `KEYBOARD_FIFO` is set, we read from the path specified there instead as a named pipe.
|
||||||
|
5.2 Regardless, each message is sent to the server with the prefix `@{payload delimiter}`.
|
||||||
|
|
||||||
``` go
|
``` go
|
||||||
--- 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}
|
||||||
@ -36,6 +35,7 @@ The base64 authentication token is loaded from the environment variable `KEYBOAR
|
|||||||
|
|
||||||
--- setup client
|
--- setup client
|
||||||
|
|
||||||
|
@{handle version command}
|
||||||
@{load connection URL from second CLI argument}
|
@{load connection URL from second CLI argument}
|
||||||
@{get authTokenInput from environment}
|
@{get authTokenInput from environment}
|
||||||
@{add xdotool if non qwerty function}
|
@{add xdotool if non qwerty function}
|
||||||
@ -91,23 +91,24 @@ if !strings.HasPrefix(connectionURL, "ws://") && !strings.HasPrefix(connectionUR
|
|||||||
|
|
||||||
## Sending keys from a named pipe
|
## Sending keys from a named pipe
|
||||||
|
|
||||||
|
|
||||||
|
We create a fifo and then continuously read from it in a loop.
|
||||||
|
|
||||||
``` go
|
``` go
|
||||||
--- start client with fifo
|
--- start client with fifo
|
||||||
|
|
||||||
|
|
||||||
var inputString string
|
|
||||||
|
|
||||||
syscall.Mkfifo(clientFifoInputFile, syscall.S_IFIFO|0666)
|
syscall.Mkfifo(clientFifoInputFile, syscall.S_IFIFO|0666)
|
||||||
|
|
||||||
|
inputString := ""
|
||||||
for {
|
for {
|
||||||
input, err := ioutil.ReadFile(clientFifoInputFile)
|
readData, err := ioutil.ReadFile(clientFifoInputFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
inputString = addXDoToolIfNonQWERTY(string(input))
|
|
||||||
input = []byte(inputString)
|
inputString = addXDoToolIfNonQWERTY(string(readData))
|
||||||
|
input := []byte("@{payload delimiter}" + inputString)
|
||||||
if len(input) > 0 {
|
if len(input) > 0 {
|
||||||
fmt.Println("send" + strings.Replace(string(input), " ", "space", 10))
|
|
||||||
err = client.WriteMessage(websocket.TextMessage, input)
|
err = client.WriteMessage(websocket.TextMessage, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("write:", err)
|
log.Fatal("write:", err)
|
||||||
@ -146,8 +147,7 @@ for {
|
|||||||
}
|
}
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
fmt.Println("send" + strings.Replace(key, " ", "space", 10))
|
err = client.WriteMessage(websocket.TextMessage, []byte("@{payload delimiter}" + key))
|
||||||
err = client.WriteMessage(websocket.TextMessage, []byte(key))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("write:", err)
|
log.Fatal("write:", err)
|
||||||
}
|
}
|
||||||
@ -164,13 +164,13 @@ for {
|
|||||||
--- add xdotool if non qwerty function --- noWeave
|
--- add xdotool if non qwerty function --- noWeave
|
||||||
addXDoToolIfNonQWERTY := func(message string)(string) {
|
addXDoToolIfNonQWERTY := func(message string)(string) {
|
||||||
|
|
||||||
if strings.HasPrefix(message, "{kb_cmd:xdotool}:") {
|
if strings.HasPrefix(message, "@{use xdotool cmd}") {
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
for _, char := range message {
|
for _, char := range message {
|
||||||
if char < 32 || char > 126 {
|
if char < 32 || char > 126 {
|
||||||
if char != 8 && char != 9 && char != 10 {
|
if char != 8 && char != 9 && char != 10 {
|
||||||
return "{kb_cmd:xdotool}:" + message
|
return "@{use xdotool cmd}" + message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
Makefile
4
Makefile
@ -1,11 +1,13 @@
|
|||||||
weave:
|
weave:
|
||||||
srcweave --formatter srcweave-format --weave docs/ ReadMe.md Building.md Dependencies.md EnvironmentVariables.md LICENSE.md \
|
srcweave --formatter srcweave-format --weave docs/ ReadMe.md Building.md Dependencies.md EnvironmentVariables.md LICENSE.md \
|
||||||
security/Authentication.md security/ThreatModel.md Plumbing.md server/Server.md server/Streaming.md server/Sendkeys.md server/XdotoolCommands.md \
|
security/Authentication.md security/ThreatModel.md Plumbing.md server/Server.md server/Streaming.md server/Sendkeys.md server/XdotoolCommands.md \
|
||||||
|
server/StringCommands.md
|
||||||
Client.md tools/Tools.md tools/Editor.md tools/Input.md tools/RawCapture.md tools/TUI.md
|
Client.md tools/Tools.md tools/Editor.md tools/Input.md tools/RawCapture.md tools/TUI.md
|
||||||
util/clean.py
|
util/clean.py
|
||||||
tangle:
|
tangle:
|
||||||
srcweave --formatter srcweave-format --tangle smartkeyboard/ ReadMe.md Plumbing.md security/Authentication.md EnvironmentVariables.md Dependencies.md \
|
srcweave --formatter srcweave-format --tangle smartkeyboard/ ReadMe.md Plumbing.md security/Authentication.md EnvironmentVariables.md Dependencies.md \
|
||||||
server/Server.md server/Streaming.md server/Sendkeys.md server/XdotoolCommands.md security/ThreatModel.md Client.md tools/Tools.md tools/Editor.md tools/Input.md \
|
server/Server.md server/Streaming.md server/Sendkeys.md server/XdotoolCommands.md server/StringCommands.md \
|
||||||
|
security/ThreatModel.md Client.md tools/Tools.md tools/Editor.md tools/Input.md \
|
||||||
tools/RawCapture.md tools/TUI.md
|
tools/RawCapture.md tools/TUI.md
|
||||||
clean:
|
clean:
|
||||||
rm -rf docs
|
rm -rf docs
|
||||||
|
@ -6,7 +6,7 @@ Copyright [Kevin Froman](https://chaoswebs.net/) [Licensed under GPLv3](LICENSE.
|
|||||||
Work in progress
|
Work in progress
|
||||||
|
|
||||||
--- version
|
--- version
|
||||||
0.0.1
|
2.0.0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
--- do streaming keylogger approach
|
--- do streaming keylogger approach
|
||||||
|
|
||||||
key := ""
|
key := ""
|
||||||
if strings.HasPrefix(message_string, "{KEYDWN}") {
|
if strings.HasPrefix(message_string, "@{keydown cmd}") {
|
||||||
key = strings.TrimPrefix(string(message_string), "{KEYDWN}")
|
key = strings.TrimPrefix(string(message_string), "@{keydown cmd}")
|
||||||
k.Write(1, key)
|
k.Write(1, key)
|
||||||
} else if strings.HasPrefix(message_string, "{KEYUP}") {
|
} else if strings.HasPrefix(message_string, "@{keyup cmd}") {
|
||||||
key = strings.TrimPrefix(string(message_string), "{KEYUP}")
|
key = strings.TrimPrefix(string(message_string), "@{keyup cmd}")
|
||||||
k.Write(0, key)
|
k.Write(0, key)
|
||||||
} else if strings.HasPrefix(message_string, "{KEYHLD}") {
|
} else if strings.HasPrefix(message_string, "@{keyheld cmd}") {
|
||||||
key = strings.TrimPrefix(string(message_string), "{KEYHLD}")
|
key = strings.TrimPrefix(string(message_string), "@{keyheld cmd}")
|
||||||
k.Write(2, key)
|
k.Write(2, key)
|
||||||
} else{
|
} else{
|
||||||
for _, key := range message_string {
|
for _, key := range message_string {
|
||||||
|
@ -102,7 +102,6 @@ package server
|
|||||||
|
|
||||||
import(
|
import(
|
||||||
"net"
|
"net"
|
||||||
"time"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -6,7 +6,7 @@ Most of the time, we can use the keylogger library (which uses uinput) to effeci
|
|||||||
|
|
||||||
xdotool spawns a new process for each keypress, so it's not as effecient as keylogger.
|
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 `@{use xdotool cmd}message` where message is a utf-8 string.
|
||||||
|
|
||||||
``` go
|
``` go
|
||||||
--- streaming keyboard input
|
--- streaming keyboard input
|
||||||
@ -67,9 +67,11 @@ func clientConnected(w http.ResponseWriter, r *http.Request) {
|
|||||||
if message_string == "" {
|
if message_string == "" {
|
||||||
message_string = "\n"
|
message_string = "\n"
|
||||||
}
|
}
|
||||||
|
for _, part := range strings.Split(message_string, "@{payload delimiter}") {
|
||||||
|
message_string = part
|
||||||
@{send keys to system}
|
@{send keys to system}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
37
server/StringCommands.md
Normal file
37
server/StringCommands.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# String Commands
|
||||||
|
|
||||||
|
To control key events and the input method we use special command strings at the beginning of a message.
|
||||||
|
|
||||||
|
They are as follows:
|
||||||
|
|
||||||
|
Payload delimiter:
|
||||||
|
--- payload delimiter
|
||||||
|
{KB_MSG}
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
Xdotool typing:
|
||||||
|
|
||||||
|
--- use xdotool cmd
|
||||||
|
{KEYDOXDOTOOL}:
|
||||||
|
---
|
||||||
|
|
||||||
|
Xdotool key command:
|
||||||
|
|
||||||
|
--- use xdotool key cmd
|
||||||
|
{KEYDOXTOOLKEY}:
|
||||||
|
---
|
||||||
|
|
||||||
|
Send keys commands:
|
||||||
|
|
||||||
|
--- keydown cmd
|
||||||
|
{KEYDWN}
|
||||||
|
---
|
||||||
|
|
||||||
|
--- keyup cmd
|
||||||
|
{KEYUP}
|
||||||
|
---
|
||||||
|
|
||||||
|
--- keyheld cmd
|
||||||
|
{KEYHLD}
|
||||||
|
---
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
Currently the two commands are `type` and `key`. `type` is used to type a character and `key` is used to type a special character like `Enter` or `Backspace`.
|
Currently the two commands are `type` and `key`. `type` is used to type a character and `key` is used to type a special character like `Enter` or `Backspace`.
|
||||||
|
|
||||||
`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 '@{use xdotool cmd}', and `key` is specified by '@{use xdotool key cmd}'. If the command is not specified and `alwaysUseXdotool` is set from the environment variable, it will default to `type`.
|
||||||
|
|
||||||
|
|
||||||
``` go
|
``` go
|
||||||
--- handle xdotoool commands
|
--- handle xdotoool commands
|
||||||
|
|
||||||
if alwaysUseXdotool || strings.HasPrefix(message_string, "{kb_cmd:xdotool}:") {
|
if alwaysUseXdotool || strings.HasPrefix(message_string, "@{use xdotool cmd}") {
|
||||||
message_string = strings.TrimPrefix(message_string, "{kb_cmd:xdotool}:")
|
message_string = strings.TrimPrefix(message_string, "@{use xdotool cmd}")
|
||||||
if message_string == "" {
|
if message_string == "" {
|
||||||
message_string = "\n"
|
message_string = "\n"
|
||||||
}
|
}
|
||||||
@ -37,8 +37,8 @@ if alwaysUseXdotool || strings.HasPrefix(message_string, "{kb_cmd:xdotool}:") {
|
|||||||
doXDoTool("type", message_string)
|
doXDoTool("type", message_string)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else if strings.HasPrefix(message_string, "{kb_cmd:kxdotool}:") {
|
} else if strings.HasPrefix(message_string, "@{use xdotool key cmd}") {
|
||||||
message_string = strings.TrimPrefix(message_string, "{kb_cmd:kxdotool}:")
|
message_string = strings.TrimPrefix(message_string, "@{use xdotool key cmd}")
|
||||||
if message_string == "" {
|
if message_string == "" {
|
||||||
message_string = "\n"
|
message_string = "\n"
|
||||||
}
|
}
|
||||||
|
@ -248,13 +248,13 @@ try:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
print("Unknown key: " + str(e_code))
|
print("Unknown key: " + str(e_code))
|
||||||
if event.value == 1:
|
if event.value == 1:
|
||||||
key_str = "{KEYDWN}" + key_str
|
key_str = "@{keydown cmd}" + key_str
|
||||||
log.append(e_code)
|
log.append(e_code)
|
||||||
quit_if_necessry(log)
|
quit_if_necessry(log)
|
||||||
elif event.value == 0:
|
elif event.value == 0:
|
||||||
key_str = "{KEYUP}" + key_str
|
key_str = "@{keyup cmd}" + key_str
|
||||||
elif event.value == 2:
|
elif event.value == 2:
|
||||||
key_str = "{KEYHLD}" + key_str
|
key_str = "@{keyheld cmd}" + key_str
|
||||||
else:
|
else:
|
||||||
print("Unknown value: " + str(event.value))
|
print("Unknown value: " + str(event.value))
|
||||||
continue
|
continue
|
||||||
|
Loading…
Reference in New Issue
Block a user