Ne demandez jamais l’aide d’une IA
Divulgâchage : On me demande souvent si j’utilise l’IA dans mes activités, puis pourquoi je ne les utilises pas. Voici la réponse à ces questions.
Alors que nous rédigions notre livre sur les shellcodes, et plus particulièrement une section sur la manière de transmettre la valeur de retour d’une fonction en langage machine, nous nous sommes demandé, par curiosité, comment l’IA se serait débrouillée à notre place.
Le problème n’est pas de savoir comment transmettre la valeur de
retour d’une fonction puisqu’il suffit de désassembler n’importe quel
bout compilé par gcc
. Ce qu’on voulait, c’est trouver la
norme, la référence officielle, qui explique pourquoi c’est bien comme
ça et pas autrement qu’il faut faire.
Nous avons donc ouvert un navigateur web et été sur le moteur de
recherche bing
qui propose une interface de « discussion »
avec Chat GPT. Nous avons donc pu poser nos question à ce robot et lire
ses réponses.
Nous vous les partageons donc ici pour que vous puissiez vous faire une idée plus réaliste de leurs capacités.
Rappel déontologique : Vu que ces robots adaptent leurs réponses à l’historique des questions, utilisent un peu d’aléatoire et son régulièrement mis à jour, il est impossible de vous garantir que vous obtiendrez exactement les mêmes réponses que nous. En ce sens, nous ne pouvons pas vous « prouver » le contenu de nos échanges.
Mais contrairement aux journalistes et autres blogueurs sous influence, nous sommes des experts judiciaires et à ce titre, nous avons prêté serment : nos productions engagent notre honneur et notre conscience.
Réponses de Bing
Les traces de nos échanges sont en citation et les seules modifications sont ergonomiques, nous n’avons pas changé un mot.
Question : Comment retourner une valeur en assembleur ?
Pour retourner une valeur en assembleur, vous pouvez utiliser l’instruction
MOV
pour déplacer la valeur souhaitée dans le registre de destination. Par exemple, si vous souhaitez retourner la valeur 42, vous pouvez utiliser l’instructionMOV EAX, 42
pour déplacer la valeur 42 dans le registreEAX
. Vous pouvez ensuite utiliser l’instructionRET
pour retourner la valeur dans la pile d’appelJ’espère que cela vous aide. Si vous avez d’autres questions, n’hésitez pas à les poser.
En savoir plus : benoit-m.developpez.com, fr.wikibooks.org, wcours.gel.ulaval.ca
Je ne résiste pas à troller bassement le bot sur ses constructions de paragraphes. La première phrase, sensée être autonome et donner la réponse ne la donne pas, c’est la phrase suivante, sensée être un exemple, qui donne en fait la réponse…
De même, l’IA me fourni un code assembleur sans aucune précision. On reconnaît la syntaxe Intel utilisée sous Windows à l’ordre des opérandes (c’est l’inverse de la syntaxe AT&T utilisée sous GNU/Linux) et le processeur Intel x86 sur 32 bits au nom du registre eax. Mais pour ça, encore faut-il s’y connaître un minimum.
Le problème avec ce choix d’architecture x86 sur 32 bits, c’est que le robot ignore complètement les processeurs plus récents et répandus comme la famille x86-64 (aussi appelée amd64) qui équipe nos ordinateurs personnels depuis 20 ans ou l’architecture ARM qui équipe nos smartphones depuis 15 ans.
Sur le fond, il y a un vrai problème avec la phrase «
ret
pour retourner la valeur dans la pile d’appel ». D’un
côté parce que ret
ne retourne pas de valeur (il dépile
l’adresse de retour pour que le processeur y poursuive son exécution).
De l’autre parce que mettre la valeur de retour dans la pile serait
incohérent si on la mettait aussi dans un registre (ou alors l’IA
suppose que ret
est équivalent à un espèce de
pop eip
suivi d’un push eax
?). Bref, ça part
pas bien.
Pour les sources, le problème est plus grave. Aucune ne mentionne
l’instruction mov eax, 42
car aucune ne traite des
conventions lors d’appel de fonction. La troisième concerne ARM où les
instructions assembleurs changent. Bref, aucune ne correspond au texte
et l’IA fait plus un gloubi boulga qu’une réponse sensée.
Mais comme ce qui m’intéressait, c’était surtout la référence pour cette convention, je n’ai pas interrogé l’IA sur ces points-là et je lui ai plutôt posé cette questions :
Question : Donne m’en la preuve
Voici la preuve que l’instruction
MOV
peut être utilisée pour retourner une valeur en assembleur. Lorsque vous utilisez l’instructionMOV EAX, 42
, vous déplacez la valeur 42 dans le registreEAX
. Vous pouvez ensuite utiliser l’instructionRET
pour retourner la valeur dans la pile d’appel..J’espère que cela répond à votre question. Si vous avez d’autres questions, n’hésitez pas à les poser.
En savoir plus : hellowork.com, candidat.pole-emploi.fr, francecarriere.fr
Donc, pour qu’on comprenne bien le processus logique de preuve dans chat GPT : prouver quelque chose consiste à le redire une deuxième fois. En gros, « C’est vrai, parce que je te le dis ». Je devrais l’utiliser plus souvent avec les juges, ça m’épargnerait de longs efforts d’investigations, d’études de dossiers et de rédaction de rapport.
Mais la pépite est dans les sources fournies pour prouver que la valeur de retour doit se placer dans eax… Si vous pensiez que les précédentes sources étaient hors sujet, celles-ci sont encore mieux. Ce sont des fiches métiers, la première pour des Assembleurs au plan (tracer et découper des pièces de métal ou autres matériaux) et les deux suivantes concernent les Assembleurs de produits électroniques (comme son nom l’indique).
Pour donner une chance à Chat GPT de mieux cerner ma demande, j’ai tenté une troisième question…
Question : Ce n’est pas parce que tu le dis que c’est vrai. J’aimerais une référence ou une documentation officielle.
Je suis désolé pour la confusion. Voici une référence officielle qui explique comment retourner une valeur en assembleur: 1. Selon cette source, pour retourner une valeur en assembleur, vous pouvez utiliser l’instruction
MOV
pour déplacer la valeur souhaitée dans le registre de retour. Par exemple, si vous souhaitez retourner la valeur 42, vous pouvez utiliser l’instructionMOV EAX, 42
pour déplacer la valeur 42 dans le registre EAX. Vous pouvez ensuite utiliser l’instructionRET
pour retourner cette valeur à l’appelant.J’espère que cela vous aide. Si vous avez d’autres questions, n’hésitez pas à les poser.
En savoir plus : hellowork.com, candidat.pole-emploi.fr, francecarriere.fr
C’est ce qu’on appelle une argumentation ad nauseam. Répéter inlassablement les mêmes phrase en espérant qu’avec le temps, elles deviennent vraies. « C’est vrai parce que je le dit ».
Autres réponses de Bing
Comme je suis curieux, j’ai voulu voir si on obtenait les mêmes réponses lors d’autres tentatives et avec d’autres formulations de questions…
Sur la forme et le fond, ça reste globalement constant. Chat GPT
répète inlassablement son histoire de mov eax, 42
suivi du
ret
pour la retourner à l’appelant (avec ou non mention à
la pile). J’ai beau lui demander des références, des documentations et
ajouter l’adjectif « officiel », rien ne change fondamentalement sa
réponse.
C’est plus dans la liste des sources qu’il y a des changements.
La troisième référence sur ARM qui pointe vers l’Université de Laval a parfois été remplacée par une autre pointant vers celle de Grenoble (lig-membres.imag.fr). Ça parle toujours d’ARM, cette fois on aborde l’appel de fonction (il y a du mieux), mais rien à propos de la valeur de retour… dommage.
Lorsque je demande des références, j’ai obtenu de nombreux liens vers stackoverflow. Returning a value in x86 assembly language, Return value of a C function in ASM et How’s return value implemented in assembly level?, dont les réponses disent, en anglais, qu’il faut la mettre dans eax mais ne citent pas de norme. Lorsque je répond au robot que stackoverflow n’est pas une référence, il s’excuse… puis me fourni les mêmes liens une deuxième fois.
Lorsque j’ai demandé des choses officielles, j’ai parfois obtenu une vidéo youtube, parfois des liens vers la documentation de microsoft concernant les conventions en C/C++ pour le passage de paramètres (mais pas de valeur de retour) voir plus cocasse, vers les sites de l’État français (Légifrance, les impots, pôle emploi). Bref, rien qui corresponde.
Pour tout dire, il est même arrivé que le robot me répète d’aller voir la vidéo youtube mais remplace le lien youtube par le lien vers l’Université de Laval…
Ce n’est qu’après plusieurs essais que j’ai eu la chance d’obtenir, enfin, un lien plus intéressant vers l’Université d’Harvard (cs61.seas.harvard.edu). La page correspondante n’explique pas comment la valeur de retour est fournie mais l’auteur cite ses références :
For concreteness, we learn the x86-64 calling conventions for Linux. These conventions are shared by many OSes, including MacOS (but not Windows), and are officially called the
System V AMD64 ABI.See the official specification (source).
Ce qui nous dit, en français, que son cours suit la convention d’appel de Linux pour processeurs x86-64. Que cette convention est suivie par plein d’autres systèmes (mais pas Windows), qu’elle s’appelle « System V AMD64 ABI » et nous fourni un lien pour la consulter.
Il aura donc fallu suivre de nombreux liens inutilement pour finalement obtenir une page plus intéressante qui pointe vers la documentation officielle que j’ai demandé depuis le début. Et encore, je ne l’ai trouvée que parce que je sais déjà de quoi on parle et ce paragraphe ne répond pas entièrement à la question.
Réponses en anglais
Lorsque j’ai voulu traduire l’article en anglais, je me suis demandé si je devais traduire les questions et réponses… Alors je suis retourné sur bing pour voir ce qu’il me répondrait si je l’interrogeais en anglais. Comme il y a eu des différences, j’ai décidé de garder les deux. Voici donc les réponses en anglais.
Question : how to return a value in assembly
To return a value in assembly, you can use the
ret
instruction. This instruction pops the top of the stack into the instruction pointer register and transfers control to the calling function. The value to be returned should be placed on the stack before theret
instruction is executed. The value can be placed in a register or memory location before being pushed onto the stack. Here is an example of how to return a value in x86 assembly language:section .data result db 0 section .text global _start _start: mov eax, 5 mov [result], eax mov eax, 1 xor ebx, ebx int 0x80 section .data result db 0 section .text global _start _start: mov eax, 5 mov [result], eax mov eax, 1 xor ebx, ebx int 0x80
In this example, the value 5 is moved into the
eax
register, which is then moved into theresult
memory location. Theret
instruction is not used because this is a complete program that exits using theint 0x80
instruction. The value 5 would be returned to the calling function if this code were part of a larger program.I hope this helps! Let me know if you have any other questions.
Source : (1) ethereum.stackexchange.com, (2) learn.microsoft.com
Voici ma traduction (résumée car elle est longue) : Comment
retourner une valeur en assembleur vous devez utiliser
l’instruction ret
qui va dépiler l’adresse de retour, mais
devez d’abord empiler la valeur de retour sur la pile. Voici un exemple.
[…example en assembleur…]. Dans cet exemple on met 5 dans eax puis dans
result
. L’instruction ret
n’est pas utilisée
car c’est un programme complet qui terminer avec
int 0x80
.
La bonne nouvelle, c’est que dans cette version, Chat GPT nous annonce quelle architecture il utilise. Il est resté sur un processeur 32 bits, c’est dommage mais il y a du mieux.
Par contre, il nous dit qu’il faut empiler la valeur de retour avant
de retourner. Ce n’est pas la même chose qu’en français et c’est pire.
Car si vous empilez la valeur de retour puis appelez ret
,
cette dernière va dépiler votre valeur en la considérant comme l’adresse
de retour et y aller pour poursuivre l’exécution du programme. Du grand
n’importe quoi.
Ensuite l’exemple consiste en deux copies du même code (les lignes 1
à 12 sont identiques aux lignes 13 à 25). Il n’y a pas d’instruction
ret
ce qui rend l’exemple hors sujet. Le texte qui suit
l’exemple l’admet parce que le robot a codé un programme… et nous dit
que la valeur de retour sera en mémoire ce qui est idiot puisqu’une fois
terminé, la mémoire est vidée…
Les liens fournis parlent bien de valeur de retour mais le premier concerne des contrats intelligents et le second du visual basic. Donc rien à voir avec de l’assembleur.
J’ai donc précisé ma demande à Chat GPT.
Question : I dont want how a program returns a value but how a function return a value
I apologize for the confusion. To return a value from a function in assembly, you can use the
ret
instruction. The value to be returned should be placed in the registereax
before theret
instruction is executed. Here is an example of how to return a value from a function in x86 assembly language:section .data result db 0 section .text global _start _start: mov eax, 5 call my_function mov [result], eax mov eax, 1 xor ebx, ebx int 0x80 my_function: mov eax, 10 ret
In this example, the value 5 is moved into the
eax
register before calling the functionmy_function
. The functionmy_function
moves the value 10 into theeax
register and then executes theret
instruction, which transfers control back to the calling function and pops the top of the stack into the instruction pointer register. The value 10 is returned to the calling function and stored in theresult
memory location.I hope this helps! Let me know if you have any other questions.
Source : (1) stackoverflow.com, (2) stackoverflow.com, (3) stackoverflow.com.
Ma traduction (résumée) : Je ne veux pas savoir comment un
programme retourne une valeur mais comment une fonction retourne une
valeur. Je suis désolé, pour retourner une valeur en
assembleur vous pouvez utiliser l’instruction ret
. La
valeur à retourner devrait être mise dans le registre eax avant
d’invoquer ret
. […Exemple…] […Explications…].
Je ne sais pas pourquoi mais cette fois l’explication change et c’est
maintenant l’équivalent du mov eax, 42
(sauf qu’ici il
placera 10). L’exemple en assembleur est trop long (j’aurais supprimé
les lignes 1 à 13).
Les liens parlent bien de mettre la valeur dans eax pour retourner une valeur mais aucun ne cite de référence. Et comme c’est ce que je cherche, je reviens à Chat GPT :
Question : Ok but can you prove your claim ?
I apologize for not providing a source for my previous response. Here is a reference to the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture ¹:
The
ret
instruction pops the top of the stack into the instruction pointer register and transfers control to the calling function. The value to be returned should be placed in theeax
register before theret
instruction is executed.I hope this helps! Let me know if you have any other questions.
Source : (1) learn.microsoft.com, (2) www.wikilawschool.net, (3) www.upcounsel.com
Pour être honète, j’ai une copie (électronique) de ces fameux manuels
d’Intel et je n’y ai pas trouvé la citation ; Le début « The ret
instruction pops the » s’y trouve deux fois. En section 6.2.4.2 où le
manuel explique comment ret
fonctionne (dépile l’adresse de
la prochaine instruction à exécuter) et en section 17.1.1 à propos d’une
deuxième pile utilisée pour renforcer les contrôles sur le flux
d’exécution. Le paragraphe complet n’apparaît nul part car le manuel ne
dit pas comment retourner des valeurs de fonctions.
Les liens en source sont magiques. Le premier, sensé être celui qui mène à la documentation Intel, mène en fait à la documentation de la classe « Claim », une fonction de sécurité du language .NET. Le deuxième est une loi fédérale des États Unis d’Amérique. Le troisième concerne la gestion des défauts de fabrication… rien à voir avec de la programmation en assembleur.
La bonne réponse
Tout d’abord, il faut savoir que la façon de placer la valeur retour d’une fonction fait partie d’un ensemble d’autres questions qu’on doit résoudre pour que des programme puisse interagir via le processeur et qu’ensemble, les réponses forment une ABI, abbréviation de Application Binary Interface. C’est l’équivalent d’une API mais l’interaction entre votre code et l’autre programme n’est pas exprimée dans votre langage de programmation mais exprimée au niveau du processeur (en assembleur).
La bonne réponse est donc « ça dépend ». Car l’ABI que vous devez suivre dépend du système d’exploitation, du langage de programmation, du compilateur, du processeur. Et même lorsque vous aurez trouvé la bonne ABI, il se peut que la réponse dépende du type de la valeur de retour…
- Windows et Unix (dont GNU/Linux) ne partagent pas exactement les mêmes conventions d’appel et cette convention peut aussi changer entre les fonctions et les appels systèmes (voir au sein des appels systèmes) ;
- Presque tous les langages de programmation permettent d’appeler des fonctions écrites en C (le C++ et le python en sont deux exemples) mais l’inverse n’est, sauf rares exceptions, pas vrai ;
- Les compilateurs peuvent proposer plusieurs variantes au choix du
développeur. Par exemple,
gcc
reconnais les attributs de fonctionms_abi
etsysv_abi
(valeur par défaut) pour préciser sous quelle forme vous voulez qu’il compile vos fonctions (cf. section 6.33.33 de la documentation de gcc) ; - Les processeurs d’architectures différentes ne proposent pas les
mêmes registres (comme on l’a vu,
eax
dans la famille x86 vsr0
chez ARM) ; - La convention System V pour AMD64 utilise des conventions différentes en fonction de la classe de la valeur de retour. Par exemple, les valeurs qui tiennent sur un registre de 64 bits passent par rax (et rdx s’il y a une deuxième valeur), celles de 128 bits passent par xmm0 (et xmm1 s’il y en a une deuxième).
Et parce que ce ne serait pas amusant sinon, le cours d’Harvard référence la norme « System V AMD64 ABI » dans sa version 1.0 alors que Linux référence la version 0.99. Donc la référence trouvée en suivant des liens fournis par Bing n’est pas celle appliquée sous GNU/Linux.
Et après
Je connaissais la réponse et j’ai voulu voir si l’IA était capable de me la fournir. J’ai demandé à l’IA de me trouver la référence officielle pour la convention d’appel des fonctions. Alors que j’étais sous GNU/Linux sur architecture x86-64, l’IA ne s’est pas embêtée à me demander ces précisions et m’a fourni une réponse incohérente pour Windows sur processeur x86 32 bits en me citant des fiches métiers.
Si j’étais un enseignant amélioré par l’IA face à des futurs ingénieurs en sécurité informatique, je leur ressortirait les poncifs du genre en agrémentant de sources farfelues. Et si des élèves me demandent des précisions sur mes élucubrations ou des sources documentaires, je relirais simplement mes transparents en citant d’autres sources tout aussi farfelues. Après tout, « j’ai raison parce que je suis le prof ».
Si j’étais un expert judiciaire boosté par l’IA, et qu’un Juge me demande mon avis dans un litige, je plagierais les avis lus les plus souvent dans d’autres expertises puis, pour donner plus de poids à ma théorie, je citerais des pièces du dossier au hasard. Et lorsque les parties me feront leurs observations, je répéterais mon avis en tirant d’autres pièces au hasard. Après tout, « j’ai raison parce que c’est moi l’expert ».
Mais on ne va pas se mentir, d’autres n’ont pas attendu l’IA pour inventer ces modes de raisonnements. Nous avons tous eu des professeurs qui répétaient leur message sans répondre aux questions. Et malheureusement, certains experts ne devraient parfois plus exercer. En plagiant l’avis majoritaire et en inventant des sources, ils peuvent répondre à toutes vos questions très rapidement, c’est rassurant mais c’est un leurre.
La nouveauté, c’est peut être qu’on nous présence ce mode de raisonnement comme une avancée majeure dans l’histoire de l’humanité et un moyen efficace pour obtenir des réponses et produire des contenus de qualité. Ce n’est qu’un mythe (et ça explique le prosélytisme).
La vérité, c’est que si une IA peut faire votre travail à votre place, c’est que vous travaillez comme un cochon.
C’est peut être réactionnaire mais je n’enseigne pas grâce à l’IA, je ne délègue pas mes avis d’expert à un robot et je ne lui laisse pas mon clavier pour écrire à ma place. Je me documente, j’étudie les pièces, je mène des expériences, j’en tire des conséquences puis je construit mon message pour qu’il réponde au mieux à la question qui m’a été posée.
C’est bien plus long mais c’est le prix d’une réponse correcte et la marque de mon respect.