Brevet FR3096803A1 — publié le 20201204

Description Titre de l'invention : Procédé mis en oeuvre par ordinateur pour obscurcir un code de programme [0001] Domaine d'application [0002] La présente invention concerne le domaine de la protection de codes de programme et plus particulièrement concerne un procédé et un programme informatique pour obscurcir un code de programme d'origine. [0003] Problème général à résoudre [0004] Les actifs de propriété tels que des algorithmes, des clés cryptographiques, des iden- tifiants privés ou des données confidentielles sont de plus en plus menacés par des attaques d'ingénierie inverse. L'invention concerne des procédés pour protéger des codes de programme contre de telles attaques. La protection des codes, aussi connue sous le nom d'obscurcissement, a pour but d'empêcher de telles attaques manat-the-end, dans lesquelles les attaquants ont un contrôle total sur le code exécutable et son environnement. De nombreuses protections et attaques ont été proposées et utilisées au cours des dernières dizaines d'années. L'obscurcissement est un procédé pour protéger un code de programme contre des attaques, qui consiste à transformer un code source ou machine en un code obscurci qui est difficile à comprendre par des humains. Toutefois, une nouvelle classe d'attaques, appelée analyse sémantique, s'est récemment avérée efficace contre des procédés d'obscurcissement courants. La présente invention concerne un nouveau procédé d'obscurcissement de code de programme qui est plus résistant aux attaques par analyse sémantique. Art antérieur 100051 Un procédé d'obscurcissement a pour but de dissimuler le comportement d'un programme ou de protéger des informations personnelles telles que des algorithmes ou des clés cryptographiques en transformant le programme à protéger P en un programme P' de telle sorte que P et P' soient équivalents du point de vue sémantique. Autrement dit, P et P' doivent calculer la même fonction mais P' est plus difficile à comprendre. Une autre propriété importante est que P' est approximativement aussi efficace que P. 100061 L'art antérieur comprend plusieurs techniques d'obscurcissement pratiques. 100071 Une première technique d'obscurcissement est appelée « technique d'arithmétique booléenne mixte ». Un exemple d'une telle technique est divulgué dans la référence I I I. Ce procédé a pour but de transformer une expression arithmétique et/ou booléenne en une expression équivalente mais plus compliquée formée à partir d'une combinaison d'opérandes booléens et arithmétiques, dans le but d'être plus complexe à comprendre. 2 [0008] D'autres techniques d'obscurcissement appelées techniques de « virtualisation » et « d'aplatissement » transforment le flux de commande en une boucle d'interprétation envoyant chaque instruction. Les procédés de « virtualisation » ajoutent également un interprète machine virtuel pour un programme de bytccode personnalisé codant la sémantique de programme d'origine. Par conséquent, le flux de commande visible du programme protégé est très éloigné du flux de commande d'origine. [0009] D'autres techniques d'obscurcissement désignées par techniques à « code auto- modifiable » et de « packing » insèrent des instructions qui modifient de manière dynamique le flux des instructions exécutées. [0010] D'autres techniques sont basées sur la divergence de chemins, comme par exemple celles décrites dans les références [2] et [3]. [0011] Une autre technique divulguée dans la référence [4], introduit un diviseur de gamme et des protections par commutateur qui présentent l'inconvénient de n'être ni maniables ni puissantes. [0012] Finalement, la référence [5] définit des protections basées sur des conjectures mathé- matiques, introduisant des boucles dont la terminaison et les effets sont difficiles à prédire en général mais sont connus en pratique pour n'importe quelle valeur raisonnable des paramètres. [0013] Les plus courantes classes d'attaques contre des programmes sont appellées analyse statique et analyse dynamique. Une analyse statique, telle qu'un désassemhlage, a pour but d'analyser le code binaire lui-même pour comprendre ou extraire des informations pertinentes. Une analyse dynamique exécute ou simule une exécution pour surveiller concrètement le comportement du programme. Ces deux approches sont facilement vaincues par des procédés d'obscurcissement courants. [0014] Limites de l'art antérieur [0015] Bien que les procédés d'obscurcissement courants puissent vaincre les classes d'attaques courantes, ils sont moins efficaces contre des attaques plus élaborées telles que l'analyse sémantique. [0016] La sémantique dans la programmation informatique peut être comprise comme étant la signification d'un programme. Les attaques sémantiques ont pour but d'analyser la sémantique d'un programme pour explorer ou simplifier plus efficacement un programme. Un tel raisonnement sémantique peut, par exemple, considérer des expressions qui sont exécutées sous forme de formules pour évaluer la faisabilité ou la non-faisabilité du chemin d'un programme. [0017] Contrairement à l'analyse standard statique ou dynamique, les outils sémantiques sont robustes. L'analyse sémantique dépend de la signification d'un code qui est invariante dans tous les schémas de compilation et l'obscurcissement, et non de sa syntaxe qui est très volatile et facile à modifier. 3 [0018] Les outils sémantiques sont également capables de découvrir des chemins peu probables dans un code de programme. De nombreuses analyses sémantiques peuvent raisonner sur des jeux infinis de données entrées en une seule étape. [0019] La plupart des analyses sémantiques courantes sont dcs analyses de teintes qui suivent la progression d'entrées à travers l'exécution d'un programme, des interprétations abstraites, qui rassemblent des informations sémantiques d'un programme par raisonnement statique (sans exécution), et finalement des exécutions symboliques dynamiques, Dynamic Symbolic Exécution (DSE), qui considèrent des entrées sous forme de variables symboliques. La DSE est actuellement probablement l'attaque sémantique la plus puissante. [0020] L'exécution symbolique dynamique simule l'exécution d'un programme le long de ses chemins, en générant systématiquement des entrées pour chaque nouvelle condition de branchement découverte. Ce processus d'exploration considère des entrées sous forme de « variables symboliques » dont les valeurs ne sont pas fixes. Le moteur d'exécution symbolique suit un chemin et chaque fois qu'il rencontre une déclaration conditionnelle impliquant l'entrée, une contrainte est ajoutée à la « valeur symbolique » associée à cette entrée. La résolution de ces contraintes de manière automatique (typiquement avec dcs solvcurs de contraintes en vente libre) permet alors de générer de nouvelles valeurs d'entrée conduisant à de nouveaux chemins, en couvrant progressivement tous les chemins du programme jusqu'à une limite définie par un utilisateur. Cette technique a connu un fort renouvellement d'intérêt au cours des dix dernières années, devenant une technique de recherche de bugs prédominante. [0021] Lorsque le moteur symbolique ne peut pas parfaitement traiter certaines constructions du langage de programmation sous-jacent, typiquement des appels de systèmes ou une auto-modification, le raisonnement symbolique est imbriqué avec une analyse dynamique permettant des approximations judicieuses. Typiquement, des valeurs concrètes de temps d'exécution sont utilisées pour compléter la partie manquante des contraintes de chemin, lesquelles sont ensuite envoyées au solveur par concrétisation. Cette solution rend l'approche particulièrement robuste vis-à-vis de constructions compliquées se retrouvant dans les codes binaires obscurcis, typiquement par packing ou auto-modification, ce qui fait de l'exécution symbolique dynamique un bon candidat pour le désobscurcissement automatisé. Elle est en particulier robuste en tant qu'analyse dynamique avec la capacité supplémentaire de trouver des conditions basées sur déclencheur. [0022] Au vu de ce qui précède, il existe le besoin d'un nouveau procédé d'obscurcissement qui soit plus résistant aux attaques par analyse sémantique, en particulier à l'exécution symbolique dynamique. De nouveaux procédés de protection doivent être conçus pour résister à l'analyse automatisée avancée tout en étant efficaces en termes de durée en n'occasionnant pas de délais d'exécution élevés. De plus, les protections ne doivent pas considérablement augmenter la taille du code d'origine non protégé. [0023] Brève description de la solution [0024] L'invention fournit une solution qui est capable de résister à une analyse sémantique, en particulier à des attaques par exécution symbolique dynamique. L'invention revendiquée est conçue pour être suffisamment solide pour rendre l'analyse basée sur la sémantique automatisée insurmontable. La solution proposée inclut en outre de faibles dépassements en termes de taille de codes et de performances d'exécution et sa conception est discrète. [0025] Les procédés de protection existants repoussant les attaques par analyse sémantique sont la plupart du temps basés sur des contraintes de difficulté de résolution et ils impliquent souvent un compromis en termes de discrétion ou de délais d'exécution. [0026] L'invention fournit une solution qui est basée sur l'explosion des chemins. Un objectif de l'invention est d'augmenter considérablement le nombre de chemins dans un programme, dans une proportion telle que le temps nécessaire pour explorer le code de programme devienne prohibitif. [0027] L'invention utilise un flux de tâches pour de telles protections basées sur les chemins, constitué d'un générateur de point de branchement et d'une politique d'ancrage pour sélectionner des positions optimales dans le code de programme pour générer un point de branchement. [0028] Un point de branchement est un jeu d'instructions obscurci devant être inséré dans le code de programme afin d'augmenter le nombre de chemins. L'invention propose des points de branchement particuliers qui créent autant de nouveaux chemins qu'il y a de valeurs de variables. [0029] Selon un mode de réalisation de l'invention, de bonnes politiques d'ancrage sont in- troduites pour identifier des ancrages indépendants et des variables pertinentes afin de sélectionner les positions les plus appropriées dans le code de programme pour l'insertion de points de branchement. [0030] Invention s'applique également à n'importe quel niveau de description de code : code source, bytecode ou code binaire. Elle s'applique également à des langages de description de matériel (par exemple le langage VHDL) ou à des modèles (par exemple le langage de modélisation unifié, Unified Modeling Language, UML) tant qu'ils contiennent des constructions reflétant des affectations de variables. [0031] De manière correspondante, un aspect de l'invention consiste à fournir un procédé mis en oeuvre par ordinateur pour obscurcir un code de progranune, comprenant les étapes suivantes : sélectionner, dans le code de programme, au moins une instruction d'affectation de variable affectant une valeur de variable d'entrée à une variahle de sortie, remplacer chaque instruction d'affectation de variable sélectionnée par un jeu d'instructions obscurci qui est fonctionnellement équivalent et qui crée autant de nouveaux chemins qu'il y a de valeurs de variables d'entrée. [0032] Selon un mode de réalisation de l'invention, l'étape consistant à sélectionner au moins une instruction d'affectation de variahle comprend l'identification d'au moins une instruction d'affectation de variable dans le code de programme. [0033] Selon un mode de réalisation de l'invention, l'étape consistant à sélectionner au moins une instruction d'affectation de variahle comprend la création, dans le code de programme, d'une instruction d'affectation de variable n'ayant aucune influence sur l'exécution du programme. [0034] Selon un mode de réalisation de l'invention, le jeu d'instructions obscurci comprend au moins une boucle FOR contrôlée par la variable d'entrée via un opérateur incrémenticl. [0035] Selon un mode de réalisation de l'invention, le jeu d'instructions obscurci comprend plusieurs boucles FOR en chaîne via un opérateur incrérnenticl, chacune étant contrôlée par un octet de la variahle d'entrée. [0036] Selon un mode de réalisation de l'invention, le jeu d'instructions obscurci comprend une première instruction et une deuxième instruction exécutées séquentiellement, la deuxième instruction affectant une valeur constante donnée à la variable de sortie et la première instruction écrivant la valeur de variable d'entrée dans une adresse décalée de la valeur constante. [0037] Selon un mode de réalisation de l'invention, le procédé comprend l'étape consistant à sélectionner, dans le code de programme, plusieurs instructions d'affectation de variables, chacune appartenant à un chemin indépendant associé à une valeur d'entrée distincte du code de programme. [0038] Selon un mode de réalisation de l'invention, le procédé comprend l'étape consistant à sélectionner, dans le code de programme, au moins une instruction d'affectation de variable, la variable ayant une chaîne définition-utilisation avec à la fois une variable d'entrée du code de programme et une variable de sortie du code de programme. [0039] Un autre aspect de l'invention consiste à fournir un produit de programme in- formatique, le produit de programme informatique comprenant un support de stockage lisible pal- ordinateur dans lequel sont incorporées des instructions exécutables par ordinateur, les instructions exécutables par- ordinateur étant exécutables par un processeur pour amener le processeur à mettre en oeuvre les étapes du procédé selon n'importe quel mode de réalisation de l'invention. [0040] Encore un autre aspect de l'invention consiste à fournir un système informatique comprenant : 6 - une mémoire ayant des instructions exécutables par ordinateur et un programme dynamique d'une application ; et - un processeur pour exécuter les instructions exécutables par ordinateur, l'exécution des instructions exécutables par ordinateur amenant le processeur à exécuter les étapes selon n'importe quel mode de réalisation de l'invention. Description détaillée [0041] Les éléments, caractéristiques et avantages ci-dessus ainsi que d'autres selon l'invention, seront mieux compris à la lecture de la description suivante plus spécifique de l'invention conjointement à l'examen des figures, dans lesquelles : [0042] [fig.l1 la figure 1 illustre un organigramme selon un mode de réalisation de la présente invention, [0043] [fig.21 la figure 2 montre un premier exemple de programme de pseudo-code re- présentant un premier type de point de branchement selon un mode de réalisation de l'invention, [0044] [fig.31 la figure 3 montre un second exemple de programme de pseudo-code re- présentant un premier type de point de branchement selon un mode de réalisation de l'invention, [0045] [0046] [fig.41 la figure 4 montre un premier exemple de programme de pseudo-code re- présentant un deuxième type de point de branchement selon un mode de réalisation de l'invention, [0047] [fig.51 la figure 5 montre un second exemple de programme de pseudo-code re- présentant un deuxième type de point de branchement selon un mode de réalisation de l'invention, [0048] [fig.61 la figure 6 montre d'autres exemples de programmes de pseudo-code re- présentant d'autres types de points de branchement selon un mode de réalisation de l'invention, [0049] [fig.71 la figure 7 montre un exemple d'un programme de pseudo-code illustrant une composition de points de branchement non optimale, [0050] [fig.81 la figure 8 montre un diagramme-bloc d'un appareil selon un mode de réa- lisation de la présente invention. [0051] Selon la figure 1, il est à présent décrit un organigramme correspondant à certains exemples de réalisation de la présente invention. L'organigramme de la figure 1 et les diagrammes-blocs dans la figure illustrent l'architecture, la fonctionnalité et le fonctionnement de mises en oeuvre possibles de systèmes, procédés et produits de programmes informatiques selon divers modes de réalisation de la présente invention. À cet égard, chaque bloc dans l'organigramme ou les diagrammes-blocs peut re- 7 présenter un module, une unité, un segment ou une portion d'instructions, comprenant une ou plusieurs instructions exécutables pour mettre en oeuvre la ou les fonctions logiques spécifiées. [0052] Le procédé selon la figure 1 vise à transformer un code de programme d'origine P en un code de programme obscurci P'. Autrement dit, le code de programme P' est modifié par l'insertion d'un jeu d'instructions qui ajoute plusieurs nouveaux chemins au programme. Ce procédé fournit une protection pour le code de programme d'origine P désignée par protection basée sur les chemins. Le code de programme modifié P' doit être fonctionnellement équivalent au code de programme d'origine P mais contenir beaucoup plus de chemins que P. [0053] Le procédé selon la figure 1 comprend principalement deux étapes 101, 102. La première étape 101 consiste à sélectionner un emplacement dans le code de programme P qui est approprié sur la hase d'une politique d'ancrage. La deuxième étape 101 consiste à introduire, à l'emplacement sélectionné, un jeu d'instructions qui créent de nouveaux chemins possibles dans le programme. [0054] Le jeu d'instructions inséré à l'emplacement sélectionné est appelé point de branchement. Un point de branchement peut également être défini comme une condition de branchement dépendant d'une variable x à une adresse a dans le code et créant tout au plus y nouveaux chemins possibles. F est appelée la capacité d'un point de branchement. Par exemple, une déclaration "Si" dans un code de programme a une capacité y = 1 parce qu'elle ne crée qu'un seul chemin possible. [0055] Un point de branchement est appliqué à une instruction d'affectation de variable dans le programme. Dans certains modes de réalisation, il est appliqué afin de remplacer une instruction d'affectation de variable avec un nouveau jeu d'instructions qui est fonctionnellement équivalent mais qui crée de nouveaux chemins possibles. [0056] Dans certains autres modes de réalisation, un point de branchement est inséré à un emplacement dans le programme où aucune instruction d'affectation existante n'est présente. Dans ce cas, le nouveau jeu d'instructions qui est inséré est fonctionnellement équivalent à une affectation de variable qui ne modifie pas l'exécution du programme. Par exemple, une instruction d'affectation de variable z=x avec une variable z non utilisée dans le programme ne modifie pas l'exécution du programme. [0057] Le code de programme obscurci P' est obtenu après l'insertion de plusieurs points de branchement dans le code de programme d'origine P, à différents emplacements. [0058] Dans certains modes de réalisation de l'invention, les points de branchement sont in- troduits à des emplacements sélectionnés arbitrairement dans le programme. [0059] Dans certains autres modes de réalisation de l'invention, les emplacements sont sé- lectionnés en fonction d'une politique d'ancrage particulière, comme cela sera expliqué ci-dessous. 8 [0060] L'invention propose de nouvelles classes de points de branchement. [0061] Un premier type de point de branchement est exemplifié par des programmes de pseudo-code illustrés sur les figures 2 et 3. Il consiste à remplacer une instruction d'affectation par une ou plusieurs boucles FOR. [0062] La figure 2 illustre, du côté gauche, un code de programme d'origine P comprenant une instruction d'affectation ch = input ; input étant une variable dépendant de l'entrée et ch étant une variable locale. [0063] Selon un mode de réalisation de l'invention, le code de programme d'origine P est transformé en un code de programme obscurci P' illustré sur le côté droit de la figure 2. L'instruction d'affectation d'origine ch = input est remplacée par une boucle FOR ch= 0, for ( i=,i REVENDICATIONS[Revendication 1] Procédé mis en oeuvre par ordinateur pour obscurcir un code de programme pour le protéger contre une attaque, comprenant les étapes suivantes : - sélectionner (101), dans le code de programme, au moins une instruction d'affectation de variable affectant une valeur de variable d'entrée à une variable de sortie, - remplacer (102) chaque instruction d'affectation de variable sélectionnée par un jeu d'instructions obscurci qui est fonctionnellement équivalent et qui crée autant de nouveaux chemins qu'il y a de valeurs de variables d'entrée. [Revendication 2] Procédé mis en oeuvre par ordinateur selon la revendication 1, dans lequel l'étape consistant à sélectionner (101) au moins une instruction d'affectation de variable comprend l'identification d'au moins une instruction d'affectation de variable dans le code de programme. [Revendication 3] Procédé mis en oeuvre par ordinateur selon la revendication 1, dans lequel l'étape consistant à sélectionner (101) au moins unc instruction d'affectation de variable comprend la création, dans le code de programme, d'une instruction d'affectation de variable n'ayant aucune influence sur l'exécution du programme. [Revendication 4] Procédé mis en oeuvre par ordinateur selon l'une quelconque dcs reven- dications précédentes, dans lequel le jeu d'instructions obscurci comprend au moins une boucle FOR contrôlée par la variable d'entrée via un opérateur incrémentiel. [Revendication 5] Procédé mis en oeuvre par ordinateur selon la revendication 4, dans lequel le jeu d'instructions obscurci comprend plusieurs boucles FOR en chaîne via un opérateur incrémentiel, chacune étant contrôlée par un octet de la variable d'entrée. [Revendication 6] Procédé mis en oeuvre par ordinateur selon l'une quelconque dcs reven- dications 1 à 3, dans lequel le jeu d'instructions obscurci comprend une première instruction et une deuxième instruction exécutées séquentiellement, la deuxième instruction affectant une valeur constante donnée à la variable de sortie et la première instruction écrivant la valeur de variable d'entrée dans une adresse décalée de la valeur constante. 19 [Revendication 7] [Revendication 8] [Revendication 9] [Revendication 10] Procédé mis en oeuvre par ordinateur selon l'une quelconque des revendications précédentes, comprenant l'étape consistant à sélectionner, dans le code de programme, plusieurs instructions d'affectation de variables, chacune appartenant à un chemin indépendant associé à une valeur d'entrée distincte du code de programme. Procédé mis en oeuvre par ordinateur selon l'une quelconque des revendications précédentes, comprenant l'étape consistant à sélectionner, dans le code de programme, au moins une instruction d'affectation de variable, la variable ayant une chaîne définition-utilisation avec à la fois une variable d'entrée du code de programme et une variable de sortie du code de programme. Produit de programme informatique, le produit de programme informatique comprenant un support de stockage lisible par ordinateur dans lequel sont incorporées des instructions exécutables par ordinateur, les instructions exécutables par ordinateur étant exécutables par un processeur pour amener le processeur à mettre en oeuvre les étapes du procédé selon l'une quelconque des revendications 1 à 7. Système informatique (800), comprenant : une mémoire (803) ayant des instructions exécutables par ordinateur et un programme dynamique d'une application un processeur (801) pour exécuter les instructions exécutables par ordinateur, l'exécution des instructions exécutables par ordinateur amenant le processeur à exécuter les étapes du procédé selon l'une quelconque des revendications 1 à 7.