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’instruction MOV EAX, 42 pour déplacer la valeur 42 dans le registre EAX. Vous pouvez ensuite utiliser l’instruction RET pour retourner la valeur dans la pile d’appel

J’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’instruction MOV EAX, 42, vous déplacez la valeur 42 dans le registre EAX. Vous pouvez ensuite utiliser l’instruction RET 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’instruction MOV EAX, 42 pour déplacer la valeur 42 dans le registre EAX. Vous pouvez ensuite utiliser l’instruction RET 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 the ret 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 the result memory location. The ret instruction is not used because this is a complete program that exits using the int 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 register eax before the ret 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 function my_function. The function my_function moves the value 10 into the eax register and then executes the ret 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 the result 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 the eax register before the ret 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…

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.

« Si vous devez résoudre un gros problème, ne demandez jamais l’aide d’un cochon. », Peg dans Peg+Chat, saison 1 épisode 1

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.