--------------------------------------------------------------------------------------- II. Linux Virii Project (Part. I) Abël --------------------------------------------------------------------------------------- [ Introduction ] Voilà c'est ma toute première prestation pour IOC et je suis fier de participer à l'aventure! Pour les personnes, qui ne connaissaient pas Hianda avant la fusion des mags avec IOC, nous avions comme projet de créer un virus pour Linux basé sur les travaux de Silvio Cesare. Je pense qu'au fil des issues, une série d'article sur le projet devrait voir le jour. Suite à quelques ennuies avec la justice, je rappelle aux simples d'esprits et à ceux qui ne voient pas plus loin que le bout de leur nez qu'il s'agit d'un projet à objectif sécuritaire qui pourrait déboucher sur un anti-virus. La fusion des deux zines étant amicale et en rien une vilaine O.P.A, je vous tiens donc au courant de l'avancé du projet. Et je suis heureux de vous dire que le projet avance... Si vous voulez en savoir plus rendez-vous sur le site du groupe (www.hianda.fr.st) rubrique "project", là bas vous trouverez une dizaine de textes traitant du sujet. 0x01. Rappel : ______________ Pour la bonne compréhension de cet article, il est nécessaire que vous ayez un minimum de connaissances sur le format ELF. Je vous conseil donc d'allez lire l'article "Executable And Linkable Format(ELF)" présent sur mon site. Comme je sais que la moitié des lecteurs ne liront pas l'article cité ci-dessus, et que je suis d'une extrème bontée, je vais tout de même vous faire un petit rappel sur le format ELF. ELF signifie Executable and Linking Format, ce qui correspond entre autre au format des binaires sous Linux. Il existe plusieurs types de fichiers objets utilisant le format Elf (=e_type), voici un extrait du fichier : /* Legal values for e_type (object file type). */ #define ET_REL 1 /* Relocatable file */ #define ET_EXEC 2 /* Executable file */ #define ET_DYN 3 /* Shared object file */ [ Comment s'organise un ELF ] Un binaire au format ELF est organisé en plusieurs parties, voici une représentation simplifiée de l'organisation physique d'un fichier objet au format ELF : ELF Header Program header table Segment 1 # Segment de texte Segment 2 # Segment de donnée Section header table Section 1 . . Section n Lorsque l'on lance un binaire, le système va lire la program header table afin de pouvoir grace aux informations contenues dans cette dernière créer l'image du binaire en mémoire. Voici comment s'organise l'image du binaire en mémoire : #1 [TTTTTTTTTTTTTTTT] #2 [TTTTTTTTTTTTTTTT] #3 [TTTTTTTTTTTTPPPP] #4 [PPPPDDDDDDDDDDDD] #5 [DDDDDDDDDDDDDDDD] #6 [DDDDDDDDDDDDPPPP] T = Texte P = Padding (remplissage) D = Données Le padding sert à compléter les segments pour que chaque page représentée par #1,2,3,4,5,6 fasse 4 Ko. Si nous résumons : Linking View Execution View ============ ============== ELF header ELF header Program header table (optional) Program header table Section 1 Segment 1 ... Segment 2 Section n ... Section header table Section header table (optional) Comme vous pouvez le voir, les fichiers objets au format ELF sont composés de plusieurs parties. Aujourd'hui nous allons nous intéresser à l'une de ces parties : le Header ELF. 0x02. Le Header Elf : _____________________ Commençons par jeter un petit coup d'oeil au fichier : /* The ELF file header. This appears at the start of every ELF file. */ typedef struct { unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ Elf32_Half e_type; /* Object file type */ Elf32_Half e_machine; /* Architecture */ Elf32_Word e_version; /* Object file version */ Elf32_Addr e_entry; /* Entry point virtual address */ Elf32_Off e_phoff; /* Program header table file offset */ Elf32_Off e_shoff; /* Section header table file offset */ Elf32_Word e_flags; /* Processor-specific flags */ Elf32_Half e_ehsize; /* ELF header size in bytes */ Elf32_Half e_phentsize; /* Program header table entry size */ Elf32_Half e_phnum; /* Program header table entry count */ Elf32_Half e_shentsize; /* Section header table entry size */ Elf32_Half e_shnum; /* Section header table entry count */ Elf32_Half e_shstrndx; /* Section header string table index */ } Elf32_Ehdr; Les commentaires étant assez réduit, je vais approfondir un peu : o e_entry : Cette partie indique au système à l'aide d'une adresse virtuelle le point d'entrer à partir duquel le programme débute, transfert les donnés, puis lance le processus en mémoire. Si le fichier n'a pas de point d'entré, sa valeur est de zéro. o e_phoff : Contient l'offset en bytes à partir de la table "Program Header". o e_shoff : Contient l'offset en bytes à partir de la table "Section Header". o e_ehsize : Represente la taille en bytes du Header Elf. o e_phentsize : Represente la taille en bytes de la table "Program Header". o e_shentsize : Represente la taille en bytes de la table "Section Header". o e_phnum : Contient le nombre d'entrées dans la table "Program Header". o e_shnum : Contient le nombre d'entrées dans la table "Section Header". [ graphique récapitulatif ] ================================================================ File header ================================================================ file offset ----------------------------------------------- 0 | ELF file magic | ----------------------------------------------- 4 | bitness | endian | ELF ver | reserved | ----------------------------------------------- 8 | reserved | ----------------------------------------------- 0Ch | reserved | ----------------------------------------------- 10h | file type | machine | ----------------------------------------------- 14h | ELF ver | ----------------------------------------------- 18h | entry point | ----------------------------------------------- 1Ch | file offset of Program Header (PH) table | ----------------------------------------------- 20h | file offset of Section Header (SH) table | ----------------------------------------------- 24h | flags | ----------------------------------------------- 28h | size of this header | PH table entry size | ----------------------------------------------- 2Ch | entries in PH table | SH table entry size | ----------------------------------------------- 30h | entries in SH table |.shstrtab section index| ----------------------------------------------- 34h 0x03. Lecteur d'Header ELF : ____________________________ Avant de se lancer dans l'écriture d'un virus ou même dans une infection (sur SA machine), il est très important de comprendre concrètement comment s'organise un binaire Elf physiquement et en mémoire. Pour étudier un binaire ELF, vous devez faire un ou plusieurs programmes capables de lire "l'architecture" du fichier ELF, c'est à dire ses spécificitées. Ces types de programmes ne sont pas vraiment difficiles à coder et ont l'avantage d'être très instructifs, le tout est de bien lire et comprendre le fichier . Je viens de découvrir une librairie du nom de "libelf" qui devrait théoriquement vous faciliter la tache enfin en théorie seulement car je l'ai testé (rapidement) et celle-ci ne me donne pas entière satisfaction ; si quelqu'un réussi à maitriser la "chose", je suis preneur ... Voici pour le moment un éditeur d'Header Elf codé par mes soins : /* * Title: ELFORCE * Author: Abël for IOC MAG * Date: 01/04/02 <°(((-< * About: Lecteur d'Header Elf for Linux Virii Project * Gr33tz to: #hianda, Christian Milow, Jamu and IOC * Site: www.hianda.fr.st * Zine: www.ioc.unixlover.com */ #include #include #include void header(Elf32_Ehdr * a) { printf("\n"); printf("e_type : "); switch ((*a).e_type) { /* a->e_type et (*a).e_type st équivalents */ case 0: printf("None\n"); break; case 1: printf("Relocatable object (.o file)\n"); break; case 2: printf("Executable\n"); break; case 3: printf("Shared library\n"); break; case 4: printf("Core file\n"); break; default: printf("Unknown type\n"); } printf("e_machine : "); switch ((*a).e_machine) { case 0: printf("None\n"); break; case 2: printf("SPARC\n"); break; case 3: printf("Intel 80386\n"); break; case 4: printf("68000\n"); break; case 8: printf("MIPS RS3000\n"); break; default: printf("Unknown type\n"); } printf("e_version : "); switch (a->e_version) { case 0: printf("Invalid\n"); break; case 1: printf("ELF version 1\n"); break; default: printf("Unknown type\n"); } printf("e_entry : %p\n", (*a).e_entry); printf("e_ehsize : %d\n", (*a).e_ehsize); printf("\n"); printf("Info about Program Header\n"); printf("e_phoff : %d\n", (*a).e_phoff); printf("e_phentsize : %d\n", (*a).e_phentsize); printf("e_phnum : %d\n", (*a).e_phnum); printf("\n"); printf("Info about Section Header\n"); printf("e_shoff : %d\n", (*a).e_shoff); printf("e_shentsize : %d\n", (*a).e_shentsize); printf("e_shnum : %d\n", (*a).e_shnum); printf("\n"); } int main(int argc, char *argv[]) { int fd; Elf32_Ehdr *ehdr; printf("\n"); printf("\t\t\t\t ¤ ELF HEADER ¤\n"); printf("\n"); if (argc<2) { printf("Usage: ./elforce \n\n"); exit(1); } else printf("%s\n\n", argv[1]); if ((fd = open(argv[1], O_RDONLY)) ==-1){ fprintf(stderr, "Error cannot open [ %s ]\n\n",argv[1]); exit(1); } ehdr = (Elf32_Ehdr *) malloc(sizeof(Elf32_Ehdr)); read(fd, ehdr, sizeof(Elf32_Ehdr)); if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG)) { fprintf(stderr, "Hey!? Are you drunk?? [ %s ] is not an Elf file! ;)\n\n", argv[1]); exit(1); } header(ehdr); free(ehdr); close(fd); return (0); } Alors ?? quand je vous disais que ce n'était pas difficile !! [ Conclusion ] Voilà, l'article est terminé ; je tiens à préciser que je me suis fortement inspiré des sources du virus "brundle-fly" (http://www.roqe.org/brundle-fly/) et de celles du virus "vit" de Silvio Cesare pour écrire "elforce" ( j'ai donc très peu de mérite ). Je vous conseil d'aller jeter un coup d'oeil sur les sources de ces virus.