                                               _                   _          _ _               _            
                                              (_)                 | |        | | |             | |          
     ___ _   _ _ __   ___ _ __ ___  ___  _ __  _  ___ ___      ___| |__   ___| | | ___ ___   __| | ___  __
    / __| | | | '_ \ / _ \ '__/ __|/ _ \| '_ \| |/ __/ __|    / __| '_ \ / _ \ | |/ __/ _ \ / _` |/ _ \/ __|
    \__ \ |_| | |_) |  __/ |  \__ \ (_) | | | | | (__\__ \    \__ \ | | |  __/ | | (_| (_) | (_| |  __/\__ \
    |___/\__,_| .__/ \___|_|  |___/\___/|_| |_|_|\___|___/    |___/_| |_|\___|_|_|\___\___/ \__,_|\___||___/
              | |                                         
              |_|                                         
                                _       _           _   _             
                               (_)     (_)         | | (_)            
                                _ _ __  _  ___  ___| |_ _  ___  _ __  
                               | | '_ \| |/ _ \/ __| __| |/ _ \| '_ \ 
                               | | | | | |  __/ (__| |_| | (_) | | | |          #1
                               |_|_| |_| |\___|\___|\__|_|\___/|_| |_|
                                      _/ |                            
                                     |__/                             


    -- [ supersonics shellcodes injection part-1

--------------------------
SHELL CODE SUPERSONIQUE  /
________________________/



Jusqu'a Chuck Yeager, le mur du son etait la barriere ultime que la nature
opposait aux reves de vitesse des hommes. Mais quel mur n'a pas pour destin
de se faire perforer, que ce soit par un avion d'essai ou par un shellcode
aerodynamique ?

Dans ce papier, je prendrais l'exemple d'une attaque sur un serveur Web. Le
port vis sur la cible sera le 80, systematiquement autorise par le firewall.
Par contre pour le reste, le firewall est suppos trs coriace. Les autres
ports ouverts sont... yen a pas !

Le shellcode a tout ce qu'il faut a l'intrieur pour ouvrir un shell sur un port
donn. Le but de l'article n'est pas d'expliquer comment renvoyer un shell, mais
comment BIEN le renvoyer.



[ 1 ] ... Rudiments de dynamique des fluides

 Aux premiers temps de la conquete de l'air, les ingenieurs se battaient
 pour determiner si l'avenir appartenait au plus lourd que l'air ou au
 plus leger que l'air. En terme de shellcoding, on trouve le shell et le
 reverse shell. Bon, les explications sont moins balaises que la partie
 "avionique" du manuel dde Flight simulator mais... accrochez vos ceintures !


 shell : 1) le shellcode ouvre le port 1234 sur la cible.
         2) l'attaquant peut alors etablir une connexion sur ce port
            afin d'accder au shell.

            +-----+                       +-----+
            |     [X] -----(1)----->   [80]     |
            |  A  |                       |  C  |
            |     [Y] -----(2)-----> [1234]     |
            +-----+                       +-----+

         Dans ce premier cas, il faut que le firewall laisse passer une
         connexion sur un port entrant Y a destination d'un port 1234.

         Et ca, c'est pas gagne ! Un firewall, son boulot, c'est pas d'avoir
         des trous, sinon c'est une passoire. Donc cette connection Y -> 1234,
         hum, c'est pas evident que ca passe.

	Il faut deja tenter quelques numros "probables" au lieu de 1234. Par
        exemple Si le serveur a fait du HTTPS il y a un moment mais que cette
        fonctionnalit a ete enlevee depuis, le firewall lui n'a peut-etre pas
        ete reconfigure pour interdire le port 8080. Les ports des serveurs
        classiques sont de bons candidats. Mais si rien n'y fait, il reste le
        plan B...



 reverse shell : 1) l'attaquant ouvre le port 1234 en ecoute et envoie
            son shellcode.
         2) Le shellcode force le serveur  venir s'y connecter
            pour apporter le shell.

            +-----+                        +-----+
            |     [X]    -----(1)-----> [80]     |
            |  A  |                        |  C  |
            |     [1234] <----(2)------  [Y]     |
            +-----+                        +-----+

         Le plan B, c'est de faire initier la connexion par le serveur. Dans
         ce cas, il y a plus de chances qu'un firewall laisse passer. Une telle
         connexion a plus de chances de sembler "licite", surtout pour un firewall
         qui ne sait pas gerer les protocoles de haut niveau et complexes comme
         ftp...


 Ca n'est pas pour le plaisir de couper les cheveux en quatre. L'objectif,
 c'est bien de pouvoir se faufiler par les breches d'un firewall. Du bon choix
 des ports source et destination pour le shell/reverse shell depend la reussite
 de l'attaque.

 Reprenons. L'idee de base est de trouver un couple de ports source/destination et
 un sens de connexion afin que l'attaquant et la cible puissent communiquer :
 rendre l'etablissement de la fleche 2 possible.

 Mais cette petite logique neglige tout bonnement la fleche 1. Lors de l'envoi du
 shellcode, l'attaquant EST DEJA connecte a la cible. Et ce socket n'est pas referme
 tout seul. Si un socket se refermait tout seul, ca se saurait ! Et mes premiers
 programmes n'auraient pas eu ces fuites de ressources que j'ai traque maintes nuits !

 La troisiemme technique est la : comme le mascaret remonte la seine pour bouffer les
 curieux qui se regroupent sur les berges, le shell mascaret remonte a contre-courant
 la connexion qui a servi a deposer le shellcode dans la cible.



 shell mascaret : 1) l'attaquant envoie le shellcode a la cible.
         2) Le shellcode retrouve le socket que le processus actif
            a utilise pour le recevoir, et le recycle pour envoyer
            le shell.

            +-----+                        +-----+
            |     |                        |     |
            |  A  [X] <-----(1/2)-----> [80]  C  |
            |     |                        |     |
            +-----+                        +-----+

[ 2 ] ... Le supersonique, ou l'art du recyclage

 La tache consiste maintenant a identifier le socket deja etabli reliant
 l'ordinateur de l'attaquant a la cible. Pour l'enumeration de tous les
 ports actuellement en service sur un systeme on dispose de quantite d'apis :
   Native : NtQuerySystemInormation 16 / NtQueryObject/ NtDeviceIoControlFile
   Ip Helper : GetExtendedTcpTable / GetExtendedUdpTable

 Pour chacun on arrive facilement a savoir a quel processus il appartient.
 Mais pour savoir quel socket du serveur web correspond au port voulu, c'est
 loin d'etre automatique. Donc plutot que recuperer la liste de tous les
 ports ouverts, voire de tous les handles du systeme, puis de trier apres
 pour n'avoir que ce qui concerne le processus actif, puis de trier pour
 trouver enfin le bon socket, il serait pas mal de contourner ce sac de noeuds
 et aller droit au but.

 Petit rappel sur le socket. Le socket est un handle correspondant a un objet
 alloue dans le noyau. Le numero du socket est donc, comme tout handle, defini
 pour son seul processus. C'est un  pointeur sur une case d'un tableau, propre
 au processus, contenant l'adresse effective de l'objet en memoire dans l'espace
 d'adressage du noyau. Deux process peuvent avoir un socket numero 23, mais le
 tableau etant propre au process, 23 represente pas le meme objet en memoire et
 donc pas le meme canal de communication, pour en revenir a ce qui nous interesse.

                  
 Pour un socket donne, la fonction getpeername va s'averer tres utile. A partir
 d'un numero de socket, cette sympathique fonction remplit un buffer avec un
 sockaddr contenant l'identite du correspondant.

 int getpeername(
   SOCKET s,
   struct sockaddr* name,
   int* namelen
 );

 Petit rappel sur le sockaddr :
 struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
 };

 Et au passage sur la structure alambiquee du in_addr :
 typedef struct in_addr {
  union {
    struct {
      u_char s_b1,s_b2,s_b3,s_b4;
    } S_un_b;
    struct {
      u_short s_w1,s_w2;
    } S_un_w;
    u_long S_addr;
  } S_un;
 } in_addr;

 Au moment d'envoyer le shellcode, on connait notre identite : notre adresse IP et
 le port sortant. On peut donc fournir ces deux informations a notre shellcode sans
 aucun probleme.

 Le shellcode peut alors tester si, pour un socket :
     1) le socket est valide
     2) le correspondant est bien identifie par le couple notre_ip, notre_port

 Et si on peut faire ca pour un socket, on peut tres bien le faire en masse. Car 
 apres tout, pourquoi s'emm***er a chercher une liste des sockets valides pour
 le processus ? Autant essayer tous les nombres de 1 a MAX_SHORT. Brutal certes,
 mais o combien efficace !




[ 3 ] ... Petit code a haute concentration d'octane

 La methode est archi simple. Tellement simple et utile qu'elle ne meritait pas
 de rester enfouie au fin fond d'un obscur document angliche. Je rigole, mais le 
 document "Assembly Components" du goupe LSD, avec le petit code source qui va
 avec est un incontournable must.

 L'implementation est quasiment aussi simple que ca :

 for (i = 0; i < 32767; i++)
   if ( getpeername(i,&buffer,sizeof(sockaddr)) != SOCKET_ERROR )
     if (buffer.sin_addr.S_un.S_addr == notre_ip && buffer.sin_port == notre_port)
        break;

 Et a la sortie, i contient le socket tant convoite. On possede maintenant et
 A COUP SUR un canal de communication entre l'attaquant et la cible. A coup sur
 car c'est le shellcode lui-meme qui a ouvert la voie.

 * BANG *

 Le mur de feu, lorsqu'il est perce, a le merite de ne pas se trahir avec un bruit
 de tonnerre. Petit detail reconfortant, je trouve.

 Schematiquement, il ne manque plus qu'un petit do_exec(i) et le tour est joue.



 Tout ca pour dire qu'en matiere de programmaion systeme, la solution existe en 
 general depuis des annees. La solution a quoi ? Ben a quasiment tout. Et pourtant,
 la meilleure facon d'apprendre reste encore de se casser les dents et de redecouvrir
 plutot que d'aller la chercher, toute chaude et prete.

 C'est vraiment trop injuste. Apprendre est deja donne a peu de monde, alors innover
 j'en parle meme pas !

 
    -- [ Tolwin
