[x86 ASM - FASM] Préparation pour un ELF

Apprentissage avec un cours sous Windows dont je n'utilise pas ce dernier

Le problème exposé dans ce sujet a été résolu.

Bonsoir,

Je sais qu’il y a quelques assassins du langage d’assemblage x86 donc voici mon problème:

Pour une raison qui m’est personelle (ici), je me suis lancé, comme dirait quelqu’un ici qui se reconnaîtra, dans la jungle avec ma bite et mon couteau mais sans mon couteau.

J’ai trouvé un cours qui ma foi me semble correct seulement, l’auteur veut à tout pris assembler sous environnement Windows.

Etant un fervent utilisateur de GNU/Linux (ArchLinux) je me suis dit que pas grave on va adapter, le jeu d’instructions ne changeant pas, ni la syntaxe de FASM.

En revanche là ou ça change c’est quand on veut préparer le terrain en fonction du format de l’éxecutable. J’ai donc remplacé le PE Console par un ELF mais en ayant lu la documentation de FASM j’ai l’impression qu’il y a un petit problème: Certaines directives comme entry n’ont pas l’air de fonctionner ni même global.

Voici le code qui ne sert à rien que j’ai écrit:

; first_program source code

; ELF Format
format ELF

; =================================

section '.text' executable
    global_start
    extrn exit

_start:
    ; All begins here
    mov eax,3

    push 0
    call exit

FASM m’insulte depuis tout à l’heure dès qu’il passe la section .text en me disant que global_start est une instruction illégale.

Qué paso ?

Merci bien.

PS: Pas de troll sur la légitimité du langage d’assemblage, je souhaite juste qu’on réponde à ma question si possible, merci.


THE EDIT:

J’ai fini par trouver la solution tout seul. Connaître le langage C et avoir lu quelques bouquins systèmes m’ont aidé dans ma recherche quand même lol

Voici la solution:

1 - Quand on lit une documentation, on la lit jusqu’au bout. La partie de la doc sur le format Executable and Linkable Format

2 - Se rapeller qu’il n’y a pas 62000 interruptions système sous GNU/Linux mais une seule (0x80) qui va lire la valeur contenue dans le registre eax au moment de son appel -> Source

Pour ceux que ça intéresse et qui n’ont pas envie de télécharger les sources du kernel juste pour trouver un putain de code d’interruption -> C’est ici que ça se passe ATTENTION: Ce sont les appels systèmes pour du 32 bits, la liste date de 1999–2000, pour l’appel exit ça pose pas de soucis mais je ne sais pas si pour le dernier kernel cela est encore valable selon les appels.

3 - Voici le résultat commenté par mes soins:

; Minimal ELF executable ASM code with FASM syntax

; ELF Format
format ELF executable 3 ; L'instruction format défini le format de l'éxécutable à assembler, ici un ELF (32 bits, ELF64 pour un 64 bits)
                        ; Le nombre << magique >> '3' défini GNU/Linux comme système d'exploitation cible

entry _start ; On défini ensuite le point d'entrée (Ici le label _start)

; =================================

segment readable executable ; Début d'un nouveau segment (Pour un éxécutable sans fichiers objets. FASM autorise de ne pas passer par l'édition
                            ; de liens afin d'assembler directement notre programme. Dans le cas contraire, l'instruction segment se transforme
                            ; en '.section')

_start:
    ; Entrée du programme
    
    mov eax,1   ; On affecte la valeur 1 au registre étendu eax (mov dest,source)

    int 0x80    ; On fait appel à l'interruption système 0x80 qui se chargera de lire la valeur
                ; contenue dans le registre eax et de faire l'appel système correspondant.

; =================================

; Cela reviens à écrire en C :
;   
;   int main(void)
;   {
;       return 0;
;   }
;
; En fait la fonction C main() fait elle même appel à l'interruption système sys_exit (Lu dans mes bouquins).
;
; [Je comprends pourquoi Dieu nous a envoyé Dennis M. Ritchie du coup]

Voilà voilà ^^

+0 -0

Salut,

Mmm… J’ai une ou deux questions qui me viennent en passant ton code en revue :

  1. Tu es certain que c’est global_start et non global _start, le but étant de définir un symbole global _start ?
  2. Normalement, le symbole _start est définit lorsque tu ne te reposes pas sur la bibliothèque C de ton système, or cela semble être le cas ici puisque tu appelles la fonction exit() (sauf si call exit a un sens particulier pour fasm) ;
  3. Juste par curiosité : pourquoi utiliser fasm et non gas (GNU Assembler) ou nasm qui reste à ma connaissance bien documentés et largement utilisés sous GNU/Linux et *BSD ?

De mon point de vue, un code correct se reposant sur la bibliothèque C devrait ressembler à ceci.

.section .text                                                                                                                         
main:
        .globl main
        pushq   %rbp
        movq    %rsp, %rbp
        movq    $0, %rdi
        call    exit
        leave
        ret

Une fois compilé avec gcc test.s -o x par exemple, cela passe sans problèmes (sauf sous OpenBSD, mais c’est pas la question :-° ). Bon, c’est de l’Assembleur 64 bits, mais c’est sensiblement la même chose pour du 32 bits si ce n’est que les arguments sont passés via la pile.

+1 -0

Salut Taurre,

Merci de t’occuper de moi, je viens de trouver la solution, j’ai édité mon post juste au dessus.

En effet j’avais tout faux mais en relisant quelques passages d’un des livres que tu m’a conseillé Celui-là tout a commencé à s’éclaircir.

J’ai effectivement tenté de me reposer sur la librairie C mais vu que je n’ai pas encore vu comment le faire, ce fut un fiasco car c’est pas aussi simple que ça en à l’air.

J’avoue que je préfèrerai utiliser gas ou nasm mais comme j’ai commencé ce cours avec fasm (Utilisé aussi dans ce dit cours) et qu’il est présent sous GNU/Linux, je l’ai donc installé. Tant que rms ne vient pas me hanter dans mon sommeil tout va bien :D

Mais effectivement je suis d’accord ;)

PS: J’espère que Dominus ne va pas passer par ici, il risque de vomir…

EDIT: En faisant un file sur mon ELF 32-bit et sur un éxecutable produit par gcc en C je viens de m’aperçevoir d’un truc interessant qui confirme bien le fait que mon ELF32 est statiquement lié contrairement à l’ELF64 produit par GCC d’ou l’instruction segment au lieu de section. Et qu’en mettant le "nombre magique" 3 j’ai produit un exécutable d’un autre temps : ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, no section header

EDIT 2: En faisant quelques tests avec ce nombre à la con, il faut finalement ne rien mettre car GNU/Linux mettra ce qu’il faut et qu’en mettant 4 par exemple on vise le système cible netBSD, donc ça ne sert pas à grand chose pour les débuts. En le laissant faire il met la même cible que pour l’ELF64 écrit en C et assemblé par GCC.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte