Code impénétrable

Le code impénétrable d'un programme informatique est un code dont la compréhension est très difficile pour un humain tout en restant parfaitement compilable par un ordinateur.

Le procédé par lequel du code est rendu impénétrable est appelé brouillage[1],[2], offuscation[1], ou par anglicisme usuel obfuscation. Cette technique de programmation – qui va à l'encontre des usages habituels – a ses raisons.

C'est tout d'abord un moyen de protéger les investissements de développement d'un logiciel par des techniques de génération de code objet rendant plus difficile la rétro-ingénierie. Il consiste notamment au remplacement d'identificateurs et de labels mnémoniques par des labels non signifiants.

Il s’agit également d’un hobby pour certains programmeurs. Ce loisir consiste en l'écriture de code source dont la fonction est difficile à déterminer. L'usage d'une syntaxe illisible, de particularités sémantiques peu connues ou peu recommandables du langage utilisé ou d'algorithmes peu naturels sont différentes techniques d'obscurcissement.

La première forme d'obscurcissement concerne le code objet généré à fin de distribution d'un programme alors que la seconde concerne le code source.

Quelques obscurcissements historiques

Assembleur

Il existe des programmes éliminant tous les commentaires d'un programme-source et remplaçant toutes les étiquettes (par exemple BOUCLE, REPRISE, ERREUR par des termes moins parlants (ETI00001, ETI00002, ETI00003, voire des mélanges de O, de 0, de I et de 1 les rendant pénibles à distinguer pour un lecteur humain sans pénaliser le moins du monde le programme assembleur).

Une variante, plus perverse encore, consiste à remplacer les commentaires par des informations qui n'apportent absolument rien.

Par exemple :

      LR    15,=X'0F'       ; On charge X'0F' dans le registre 15

Turbo Pascal 3

Du temps de Turbo Pascal 3 (circa 1985) existait un programme supprimant tous les blancs non significatifs d'un code source, tassant celui-ci à raison de 255 caractères par ligne, et remplaçant toutes les variables par des combinaisons de l (L minuscule) de 1 (chiffre 1), de O (O majuscule) et de 0 (chiffre 0). Par exemple A := B + C devenait l0O1l10O:=O1ll10O0+O0O1l00ll. La nécessité de ces offuscateurs venait du fait que Turbo Pascal 3 ne permettait pas de distribuer des sous-programmes autrement que sous forme de code source[3].

Utilisation d'un langage générant de l'assembleur

Dans les années 1960 et 1970, la plupart des constructeurs utilisaient pour leurs développements des langages de type PL (PL/360, PL/M, PL/C, PL/S, PL/1600…) qui traduisaient un code source semi-évolué en assembleur. Les applications n'étant vendables à l'époque que si leur code source était disponible[4], c'est ce code assembleur généré qui était mis à disposition des clients. Ainsi, une instruction comme A=B+31; devenait :

      LR     4,B
      ADD    4,=31
      ST     4,A

Version que le client était moins enclin à modifier, d'autant que la version suivante l'aurait obligé à recommencer toutes ses modifications. Le but premier était moins de masquer le code source que de limiter les modifications des programmes par les clients, la maintenance à distance par les éditeurs étant plus difficile pour les programmes modifiés.

Batch

Bien que rudimentaire, le langage Batch (MSDOS) permet lui aussi de complexifier le code, rendant la compréhension des programmes difficile. L'instruction "Set" permet de définir une équivalence. Par exemple : Set A = B. Il est alors possible d'utiliser A à la place de B en appelant A entre deux symboles "%". Exemple : %A%. Cela devient intéressant quand on substitue une vraie instruction à une chaîne de caractères complexe.

Exemple : Set #A = Dir

L'utilisation de %#A% appellera ainsi la commande "Dir". On peut pousser le système à l'extrême en remplaçant la commande Set par une équivalence, et utiliser cette équivalence pour encoder de nouvelles instructions.

Exemple :

      Set ¯=Set%þ%
      %¯% ð=If Exist%þ%
      %¯% =Echo%þ%

      ...//...

      %% þAkhenatonþ>>%2
      %ð% î%2 %Þ% F%þ%
      Ren %2 î%2%þ%
      %% @%% Off>%2%þ%
      Find "þ"<%ê%>>%2
      %% %ð% î%2 %Þ% E>>%2%þ%

Cette technique de masquage de code est utilisée par certains virus informatiques (Akhenaton, Catlord, etc.) codés en Batch. Ces virus sont rudimentaires et peu fréquents mais ont le mérite d'avoir su exploiter les failles d'un langage primitif comme le Batch et masquer ainsi leur code viral.

Fortran

En plus des techniques classiques valables pour tous les langages, l'obscurcissement d'un code Fortran utilisant le format fixe utilisé avant Fortran 90 peut être obtenu en supprimant toutes les espaces (y compris entre un mot clé du langage et un nom de variable) et en utilisant des noms différents pour une même variable dans différentes parties du code par le biais des EQUIVALENCE ou des COMMON. Mais le format libre utilisé depuis Fortran 90 ne permet plus cette suppression de toutes les espaces. Les instructions EQUIVALENCE et COMMON sont considérés obsolescentes depuis la norme Fortran 2018.

Obscurcissement algorithmique

La division en sous-chaînes égales d'une chaîne de longueur n prouve que n est non premier (si n ≠ 2). L'usage d'une expression rationnelle pour un tel test est donc possible, bien que peu naturel et plutôt lent. Une preuve de concept a été écrite en Perl[5].

Une forme particulière d'obscurcissement est un programme multilingue qui fait la même chose quand il est exécuté par différents interpréteurs ou compilateurs. Il existe ainsi un programme qui s'exécute indifféremment interprété par Perl et compilé en C, et dont cela constitue d'ailleurs le seul intérêt[6],[7].

Autres

L'obscurcissement utilise souvent des recoins peu utilisés d'un langage et peut quelquefois contribuer à la détection de bugs.

L'IOCCC (International Obfuscated C Code Contest) est le concours annuel d'obscurcissement en C.
The Perl Journal a organisé des concours d'obscurcissement en Perl.
Certains JAPH sont des obscurcissements.

Certains langages comme le C, le Perl et l'APL se prêtent très bien à l'obscurcissement. Dans The Humble Programmer, Edsger Dijkstra a des mots très durs pour les langages riches qui se prêtent à de telles techniques et se fait l'avocat de langages plus modestes. Larry Wall affirme en revanche qu'un langage qui essaierait d'interdire de mauvaises pratiques telles que l'obscurcissement empêcherait aussi d'écrire des programmes légitimes tels que les unilignes.

Références

  1. a et b « brouillage », Grand Dictionnaire terminologique, Office québécois de la langue française (consulté le ).
  2. Commission d’enrichissement de la langue française, « brouillage », sur FranceTerme, ministère de la Culture (consulté le ).
  3. "Borland Turbo Pascal 3.x. Borland Turbo Pascal is a Pascal programming language compiler"
  4. http://www.redbooks.ibm.com/redbooks/pdfs/sg247000.pdf page 45 : « Few people know that open source was the business model that software began with! In the 1960s, nobody would buy a computer (a huge investment at that time) that was not immediately ready for some use. Software had to be given away by manufacturers as “a way to sell the hardware faster,” and free of charge for that reason. The source code was distributed so that anybody could change it. At the time, nobody would or could use a computer without having programming skills.

    In the 1970s, legislation in many countries decided that giving away software for free was unfair competition toward new companies that were developing competitive software and selling it for a living. Therefore, software had to be billed by law. It was still lawful to give the source for free as an option to anybody who bought a software product, and IBM did just this.

    In the late 1970s, centralized support to end-users began to get difficult because they did not know whether they used “vanilla” software (object code from IBM) or software modified by their IT group. Since only very few people ordered the source, but were causing most of the work, IBM had to adopt an object-code-only (OCO) distribution mode. This may have been one of the reasons universities began to switch from VM/CMS to UNIX, because UNIX code was available to play with.
     »
  5. Expression rationnelle pour tester la primalité d'un nombre.
  6. (en) « Perl is C ».
  7. (en) « C is Perl ».

Annexes

Voir aussi

Liens externes