Sécurité dans le .NET Framework :
La sécurité est un vaste sujet, un des piliers clé de toutes applications. L’objectif d’intégrer la sécurité dans les développements applicatifs est d’offrir un degré de protection adaptée en fonction du danger potentiel.
Vol de propriété intellectuelle
Cliquez pour révéler
Cliquez pour masquer
Loading Image
La crainte de tout les développeurs; la décompilation. Comment décompiler un programme en .NET ? Rien de plus simple et des 'développeurs' .NET s’y emploie chaque jour sur le framework pour parfaire ses connaissances avec des outils comme IL***M ou Refl****r qui est très largement utilisé.
Obfuscation
L’obfuscation est l’art d'obscurcir le code. Il existe bonne une quarantaine d’algorithmes d’obfuscation. Un algorithme d’obfuscation possède en général 3 mesures permettant de connaître son efficacité : sa puissance, sa robustesse et son coût.
On diffère un bonne obfuscateur d'un moins bon selon la difficulté de lecture du code pour un humain. La plupart des algorithmes d'obfuscation supprime la totalité des commentaires dans le code qui pourrait aider à comprendre son fonctionnement. Un autre algorithme modifie tous les noms de variables du code.
Prenons pour exemple une fonction tirée au pif de 'EuuBot'.
private void GetBorder(int column, int line)
{
_borders = new byte[8];
if (line == 0)
_borders[0] = 1; //Bord haut 3 cases
if (line == 1)
_borders[1] = 1; //Bord haut 1 case
if (line == 39)
_borders[2] = 1; //Bord bas 3 cases
if (line == 38)
_borders[3] = 1; //Bord bas 1 case
if (column == 0 && _pair)
_borders[4] = 1; //Bord gauche 3 cases
if (column == 0 && !Pair)
_borders[5] = 1; //Bord gauche 1 case
if (column == 13 && !_pair)
_borders[6] = 1; //Bord droite 3 cases
if (column == 13 && _pair)
_borders[7] = 1;
}
Peut-être transformé de la manière suivante:
private void GetBorder(int EEFEFEEFEFEFFEEFFE, int EEFEFEFEFFEFFEEFFE)
{
EEFEFEFEFFEEEFFFFE = new byte[8];
if (EEFEFEFEFFEFFEEFFE == 0)
EEFEFEFEFFEEEFFFFE[0] = 1;
if (EEFEFEFEFFEFFEEFFE == 1)
EEFEFEFEFFEEEFFFFE[1] = 1;
if (EEFEFEFEFFEFFEEFFE == 39)
EEFEFEFEFFEEEFFFFE[2] = 1;
if (EEFEFEFEFFEFFEEFFE == 38)
EEFEFEFEFFEEEFFFFE[3] = 1;
if (EEFEFEEFEFEFFEEFFE == 0 && _pair)
EEFEFEFEFFEEEFFFFE[4] = 1;
if (EEFEFEEFEFEFFEEFFE == 0 && !Pair)
EEFEFEFEFFEEEFFFFE[5] = 1;
if (EEFEFEEFEFEFFEEFFE == 13 && !_pair)
EEFEFEFEFFEEEFFFFE[6] = 1;
if (EEFEFEEFEFEFFEEFFE == 13 && _pair)
EEFEFEFEFFEEEFFFFE[7] = 1;
}
Le programme fonctionnera toujours de la même de la même manière.
Il y a plusieurs autres éléments à prendre en compte,
La perte de performances à l'exécution par l'utilisation d'un algorithme d'obfuscation. Plus l'algorithme est robuste, plus il est coûteux.
L’exemple ci-dessous est tiré de l’utilitaire d’offuscation de Mpoware en version beta (code source, puis code offusqué). Cet outil est le seul du marché qui permet d’offusquer du code source C# (offuscation pré-compilation) et non du MSIL (offuscation post-compilation) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Mpoware.CSharp.Parser.Tests
{
public class Test5_ClassModifiers
{
// Avec un commentaire une ligne
/*
** Small comment
** Delimited $$$
*/
public void Say(string message)
{
i = 0;
Console.WriteLine("Hello " + /*mon message*/ message);
}
}
}
Offusqué de la manière suivante:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Mpoware.CSharp.Parser.Tests
{
public class Test5_ClassModifiers
{
public void Say(string lCn)
{
int bFvkZBBQMMybaxvs;
bFvkZBBQMMybaxvs = 0;
if (bFvkZBBQMMybaxvs == 0) goto sdlfhsqdfmkjf;
fmkjdshfkjf: if (bFvkZBBQMMybaxvs == 1) { Console.WriteLine(GetString(new int[] { 2, 2, -3, 0, -1, 3 }) + lCn); goto end; }
sdlfhsqdfmkjf: ADDKSHFDDRH(bFvkZBBQMMybaxvs); bFvkZBBQMMybaxvs++; if (bFvkZBBQMMybaxvs == 1) { goto fmkjdshfkjf; } else { goto fmkjdshfkjf5; };
bFvkZBBQMMybaxvs = 0;
if (bFvkZBBQMMybaxvs == 0) goto sdlfhsqdfmkjf;
fmkjdshfkjf5: if (bFvkZBBQMMybaxvs == 1) { Console.WriteLine(GetString(new int[] { 2, 2, -3, 0, -1, 3 }) + lCn); goto end; }
sdlfhsqdfmkjf6: ADDKSHFDDRH(bFvkZBBQMMybaxvs); bFvkZBBQMMybaxvs++; goto fmkjdshfkjf;
end1: ;
bFvkZBBQMMybaxvs = 0;
if (bFvkZBBQMMybaxvs == 0) goto sdlfhsqdfmkjf;
fmkjdshfkjf1: if (bFvkZBBQMMybaxvs == 1) { Console.WriteLine(GetString(new int[] { 2, 2, -3, 0, -1, 3 }) + lCn); goto end; }
sdlfhsqdfmkjf2: ADDKSHFDDRH(bFvkZBBQMMybaxvs); bFvkZBBQMMybaxvs++; goto fmkjdshfkjf;
end2: ;
bFvkZBBQMMybaxvs = 0;
if (bFvkZBBQMMybaxvs == 0) goto sdlfhsqdfmkjf;
fmkjdshfkjf3: if (bFvkZBBQMMybaxvs == 1) { Console.WriteLine(GetString(new int[] { 2, 2, -3, 0, -1, 3 }) + lCn); goto end; }
sdlfhsqdfmkjf4: ADDKSHFDDRH(bFvkZBBQMMybaxvs); bFvkZBBQMMybaxvs++; goto fmkjdshfkjf;
end3: ;
end: return; ;
}
private int ADDKSHFDDRH(int bFvkZBBQMMybaxvs)
{
return bFvkZBBQMMybaxvs++;
}
private string GetString(int[] p)
{
StringBuilder s = new StringBuilder();
int[] al = new int[6] { 111, 108, 72, 32, 101, 34 };
int i = 0;
for (int k = 0; k < p.Length; k++)
{
i += p[k++]; s.Append((char)al);
}
return s.ToString();
}
}
}
De moins en moins de développeurs choisissent de protéger leurs applications via des obfuscateurs car il existe de gros inconvénients:
- Brouillage peu robuste
- Il existe des décompilateurs tels que Salamander .NET qui réduisent l’utilité de la plupart des offuscateurs
- Il peut être plus difficile de débugger un programme offusqué : la pile d’appels est elle-même difficile à lire par l’auteur du programme si l’offuscateur ne propose pas une table de lecture inverse…
Je me permet de vous fournir une liste des meilleurs obfucateurs .NET. (Source: Wikipedia)
Cliquez pour révéler
Cliquez pour masquer
Loading Image
La suite du Tutoriel portera sur : Protection des assemblies par cryptage