Compare commits
No commits in common. "a2e9ce6aeb8c9b7fe9bf08f16d8cabc33003da8f" and "3d9a31f4af05adb71a7be368307554a4e8b86450" have entirely different histories.
a2e9ce6aeb
...
3d9a31f4af
26
Client.md
26
Client.md
@ -7,11 +7,12 @@ 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.
|
||||||
5.1 If the environment variable `KEYBOARD_FIFO` is set, we read from the path specified there instead as a named pipe.
|
6. If KEYBOARD_FIFO is specified as an environment variable, 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}
|
||||||
@ -35,7 +36,6 @@ 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,24 +91,23 @@ 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 {
|
||||||
readData, err := ioutil.ReadFile(clientFifoInputFile)
|
input, err := ioutil.ReadFile(clientFifoInputFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
inputString = addXDoToolIfNonQWERTY(string(input))
|
||||||
inputString = addXDoToolIfNonQWERTY(string(readData))
|
input = []byte(inputString)
|
||||||
input := []byte(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)
|
||||||
@ -147,6 +146,7 @@ for {
|
|||||||
}
|
}
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
fmt.Println("send" + strings.Replace(key, " ", "space", 10))
|
||||||
err = client.WriteMessage(websocket.TextMessage, []byte(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, "@{use xdotool cmd}") {
|
if strings.HasPrefix(message, "{kb_cmd:xdotool}:") {
|
||||||
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 "@{use xdotool cmd}" + message
|
return "{kb_cmd:xdotool}:" + message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
Makefile
4
Makefile
@ -1,13 +1,11 @@
|
|||||||
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 server/StringCommands.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 \
|
||||||
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
|
||||||
3.0.0
|
0.0.1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
--- do streaming keylogger approach
|
--- do streaming keylogger approach
|
||||||
|
|
||||||
key := ""
|
key := ""
|
||||||
if strings.HasPrefix(message_string, "@{keydown cmd}") {
|
if strings.HasPrefix(message_string, "{KEYDWN}") {
|
||||||
key = strings.TrimPrefix(string(message_string), "@{keydown cmd}")
|
key = strings.TrimPrefix(string(message_string), "{KEYDWN}")
|
||||||
k.Write(1, key)
|
k.Write(1, key)
|
||||||
} else if strings.HasPrefix(message_string, "@{keyup cmd}") {
|
} else if strings.HasPrefix(message_string, "{KEYUP}") {
|
||||||
key = strings.TrimPrefix(string(message_string), "@{keyup cmd}")
|
key = strings.TrimPrefix(string(message_string), "{KEYUP}")
|
||||||
k.Write(0, key)
|
k.Write(0, key)
|
||||||
} else if strings.HasPrefix(message_string, "@{keyheld cmd}") {
|
} else if strings.HasPrefix(message_string, "{KEYHLD}") {
|
||||||
key = strings.TrimPrefix(string(message_string), "@{keyheld cmd}")
|
key = strings.TrimPrefix(string(message_string), "{KEYHLD}")
|
||||||
k.Write(2, key)
|
k.Write(2, key)
|
||||||
} else{
|
} else{
|
||||||
for _, key := range message_string {
|
for _, key := range message_string {
|
||||||
|
@ -102,6 +102,7 @@ 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 `@{use xdotool cmd}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.
|
||||||
|
|
||||||
``` go
|
``` go
|
||||||
--- streaming keyboard input
|
--- streaming keyboard input
|
||||||
@ -57,6 +57,7 @@ func clientConnected(w http.ResponseWriter, r *http.Request) {
|
|||||||
c.WriteMessage(websocket.TextMessage, []byte("authenticated"))
|
c.WriteMessage(websocket.TextMessage, []byte("authenticated"))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
time.Sleep(25 * time.Millisecond)
|
||||||
_, message, err := c.ReadMessage()
|
_, message, err := c.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("read:", err)
|
log.Println("read:", err)
|
||||||
@ -67,11 +68,9 @@ 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}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
# 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 '@{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`.
|
`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
|
||||||
--- handle xdotoool commands
|
--- handle xdotoool commands
|
||||||
|
|
||||||
if alwaysUseXdotool || strings.HasPrefix(message_string, "@{use xdotool cmd}") {
|
if alwaysUseXdotool || strings.HasPrefix(message_string, "{kb_cmd:xdotool}:") {
|
||||||
message_string = strings.TrimPrefix(message_string, "@{use xdotool cmd}")
|
message_string = strings.TrimPrefix(message_string, "{kb_cmd:xdotool}:")
|
||||||
if message_string == "" {
|
if message_string == "" {
|
||||||
message_string = "\n"
|
message_string = "\n"
|
||||||
}
|
}
|
||||||
@ -37,8 +37,8 @@ if alwaysUseXdotool || strings.HasPrefix(message_string, "@{use xdotool cmd}") {
|
|||||||
doXDoTool("type", message_string)
|
doXDoTool("type", message_string)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
} else if strings.HasPrefix(message_string, "@{use xdotool key cmd}") {
|
} else if strings.HasPrefix(message_string, "{kb_cmd:kxdotool}:") {
|
||||||
message_string = strings.TrimPrefix(message_string, "@{use xdotool key cmd}")
|
message_string = strings.TrimPrefix(message_string, "{kb_cmd:kxdotool}:")
|
||||||
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 = "@{payload delimiter}@{keydown cmd}" + key_str
|
key_str = "{KEYDWN}" + 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 = "@{payload delimiter}@{keyup cmd}" + key_str
|
key_str = "{KEYUP}" + key_str
|
||||||
elif event.value == 2:
|
elif event.value == 2:
|
||||||
key_str = "@{payload delimiter}@{keyheld cmd}" + key_str
|
key_str = "{KEYHLD}" + 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