Aller au contenu principal

Obfusquez votre code PHP

Protégez votre code PHP grâce à l'obfuscation. Découvrez comment fonctionne le script php_obfuscator et si des outils d'IA comme Copilot arrivent encore à désobfusquer votre code source propriétaire.

· 4 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Journal des modifications

Dernière
Updated PHP Docker image from php:7.4-fpm (EOL Nov 2022) to php:8.3-fpm in all examples.

Obfusquez votre code PHP

⚡
TL;DR

Cet article teste si l'obfuscation de code PHP (avec le script php_obfuscator de l'auteur, qui supprime les espaces et renomme les identifiants en chaînes aléatoires) protège encore le code propriétaire à l'ère de l'IA. Un jeu du pendu généré par Gemini est obfusqué et continue de fonctionner correctement, mais Copilot arrive ensuite à le désobfusquer entièrement, en code lisible et commenté — de quoi se demander si l'obfuscation vaut encore la peine.

Il y a quelques années, je vendais un logiciel appelé aeSecure, un Web Application Firewall. Pour éviter que mon code propriétaire soit récupéré par quelqu'un qui pourrait ensuite le revendre, par exemple, j'avais développé un script d'obfuscation.

Depuis, j'ai publié une version réutilisable de ce script : https://github.com/cavo789/php_obfuscator.

Et si, aujourd'hui, avec l'intelligence artificielle, ce type de code n'avait plus aucun intérêt ? L'objectif de cet article est de voir s'il est toujours pertinent de rendre son code illisible.

Obtenir un code qui n'existait pas encore : demandez à Gemini​

Juste pour disposer d'un peu de code PHP en exemple pour cet article, créons un jeu du pendu avec l'intelligence artificielle.

Demander à Gemini

Voici le code proposé par Gemini. Enregistrez-le sur votre disque sous le nom hangman.php :

<?php
function generateWordList() {
// Replace these with your own word list
return [
"apple",
"banana",
"orange",
"computer",
"programming",
];
}
function getRandomWord($wordList) {
$randomIndex = array_rand($wordList);
return $wordList[$randomIndex];
}
function displayHangman($guessesLeft) {
$stages = [
"[ O ]",
"[ | ]",
"[ /| ]",
"[ /|\\ ]",
"[ | ]",
"[ / ]",
"Wrong guess: ",
];
echo $stages[$guessesLeft] . PHP_EOL;
}
function displayWord($word, $guessedLetters) {
$displayedWord = "";
for ($i = 0; $i < strlen($word); $i++) {
$letter = $word[$i];
if (in_array($letter, $guessedLetters)) {
$displayedWord .= $letter . " ";
} else {
$displayedWord .= "_ ";
}
}
echo trim($displayedWord) . PHP_EOL;
}
function playHangman() {
$wordList = generateWordList();
$word = getRandomWord($wordList);
$guessedLetters = [];
$guessesLeft = 6;
while ($guessesLeft > 0) {
displayHangman($guessesLeft);
displayWord($word, $guessedLetters);
echo "Guess a letter: ";
$guess = trim(fgets(STDIN));
if (strlen($guess) !== 1 || !ctype_alpha($guess)) {
echo "Please enter a single letter." . PHP_EOL;
continue;
}
$guess = strtolower($guess);
if (in_array($guess, $guessedLetters)) {
echo "You already guessed that letter." . PHP_EOL;
continue;
}
$guessedLetters[] = $guess;
if (strpos($word, $guess) === false) {
$guessesLeft--;
}
if (str_replace(" ", "", displayWord($word, $guessedLetters)) === $word) {
echo "Congratulations! You guessed the word." . PHP_EOL;
break;
}
}
if ($guessesLeft === 0) {
displayHangman($guessesLeft);
echo "You ran out of guesses. The word was: " . $word . PHP_EOL;
}
}
playHangman();

Ce script implémente le jeu du pendu en PHP. Il génère une liste de mots, en choisit un au hasard, puis demande au joueur de deviner des lettres jusqu'à trouver le mot ou épuiser ses essais. Le jeu affiche l'état du pendu et les lettres devinées correctement, et termine quand le joueur gagne ou perd.

Pour jouer, il suffit de lancer docker run -it -v ${PWD}:/src -w /src php:8.3-fpm php hangman.php (voyez La façon la plus simple de lancer un script / site PHP si cette commande vous semble cryptique).

Comme vous allez le voir, le script fonctionne très bien sans aucune modification !

En train de jouer

Obfusquer​

Maintenant, nous allons rendre ce code illisible en supprimant les espaces et les retours à la ligne inutiles, et en remplaçant les noms par des lettres aléatoires. Par exemple, remplacer le nom de fonction playHangman par une chaîne aléatoire comme ppny. Et pour rendre le code encore plus illisible, je ne choisirai que des chaînes du type ppmx, ppnx, ppny et ainsi de suite.

Pour réaliser cette obfuscation, téléchargez simplement mon script https://github.com/cavo789/php_obfuscator/blob/main/src/minify.php et enregistrez-le sur votre disque sous le nom minify.php. Créez aussi un fichier appelé settings.json avec ce contenu :

{
"replace": {
"getRandomWord":"ppmx",
"displayHangman":"ppnx",
"playHangman":"ppny",
"displayWord":"ppnz",
"guessesLeft":"ppnc",
"guessedLetters":"ppnt",
"randomIndex":"ppmw",
"wordList":"ppmu",
"generateWordList":"ppms",
"displayedWord":"ppmb",
"stages":"ppmc"
}
}

Ce fichier de configuration définit un mappage de renommage pour obfusquer les noms de fonctions et variables d'un jeu du pendu. Chaque identificateur lisible est remplacé par un code court et opaque (comme ppmx, ppnx, etc.) pour réduire la taille du code ou le rendre plus difficile à comprendre.

À ce stade, vous avez trois fichiers dans votre dossier :

>user@machine: ~/yourproject

Il est temps de rendre le fichier hangman.php illisible en lançant docker run -it -v ${PWD}:/src -w /src php:8.3-fpm php minify.php input=hangman.php output=hangman_minify.php.

Obfusquer votre code PHP

Vous avez maintenant un nouveau fichier appelé hangman_minify.php :

<?php
// cspell:disable
function ppms(){return [
"apple",
"banana",
"orange",
"computer",
"programming",
];}
function ppmx($ppmu){$ppmw=array_rand($ppmu);return $ppmu[$ppmw];}
function ppnx($ppnc){$ppmc=[
"[ O ]",
"[ | ]",
"[ /| ]",
"[ /|\\ ]",
"[ | ]",
"[ / ]",
"Wrong guess: ",
];echo $ppmc[$ppnc].PHP_EOL;}
function ppnz($word,$ppnt){$ppmb="";
for ($i=0; $i < strlen($word); $i++){$letter=$word[$i];if(in_array($letter,$ppnt)){$ppmb .=$letter." ";}else{$ppmb .="_ ";}}echo trim($ppmb).PHP_EOL;}
function ppny(){$ppmu=ppms();$word=ppmx($ppmu);$ppnt=[];$ppnc=6;while ($ppnc > 0){
ppnx($ppnc);
ppnz($word,$ppnt);echo "Guess a letter: ";$guess=trim(fgets(STDIN));if(strlen($guess) !==1||!ctype_alpha($guess)){echo "Please enter a single letter.".PHP_EOL;continue;}$guess=strtolower($guess);if(in_array($guess,$ppnt)){echo "You already guessed that letter.".PHP_EOL;continue;}$ppnt[]=$guess;if(strpos($word,$guess)===false){$ppnc--;}
if(str_replace(" ", "", ppnz($word,$ppnt))===$word){echo "Congratulations! You guessed the word.".PHP_EOL;break;}}
if($ppnc===0){
ppnx($ppnc);echo "You ran out of guesses. The word was: ".$word.PHP_EOL;}}
ppny();

Ce script implémente un jeu du pendu en ligne de commande. Le joueur doit deviner les lettres d'un mot caché, en disposant d'un nombre limité de tentatives avant que le jeu ne se termine. Le programme affiche l'état du pendu, les lettres devinées et demande continuellement au joueur d'entrer une lettre jusqu'à la victoire ou la défaite.

Ce que vous voyez ici, c'est la nouvelle version du fichier hangman.php, et elle fonctionne toujours. Vous pouvez le vérifier en lançant docker run -it -v ${PWD}:/src -w /src php:8.3-fpm php hangman_minify.php.

Rendre le code lisible à nouveau : demandez à Copilot​

Demander à Copilot

La première fois, Copilot a conservé mes noms de fonctions minifiés. En lui demandant Can you suggest another version?, Copilot propose ce code :

Réécriture du code

<?php
// Define an array of words
function getRandomWord()
{
$words = [
"apple",
"banana",
"orange",
"computer",
"programming",
];
return $words[array_rand($words)];
}
// Display hangman art based on the number of incorrect guesses
function displayHangman($incorrectGuesses)
{
$hangmanArt = [
"[ O ]",
"[ | ]",
"[ /| ]",
"[ /|\\ ]",
"[ | ]",
"[ / ]",
];
echo $hangmanArt[$incorrectGuesses] . PHP_EOL;
}
// Display the word with guessed letters revealed
function displayWord($word, $guessedLetters)
{
$displayedWord = "";
foreach (str_split($word) as $letter) {
if (in_array($letter, $guessedLetters)) {
$displayedWord .= $letter . " ";
} else {
$displayedWord .= "_ ";
}
}
echo trim($displayedWord) . PHP_EOL;
}
// Main game loop
function playHangman()
{
$wordToGuess = getRandomWord();
$guessedLetters = [];
$incorrectGuesses = 6;
while ($incorrectGuesses > 0) {
displayHangman($incorrectGuesses);
displayWord($wordToGuess, $guessedLetters);
echo "Guess a letter: ";
$guess = trim(fgets(STDIN));
if (strlen($guess) !== 1 || !ctype_alpha($guess)) {
echo "Please enter a single letter." . PHP_EOL;
continue;
}
$guess = strtolower($guess);
if (in_array($guess, $guessedLetters)) {
echo "You already guessed that letter." . PHP_EOL;
continue;
}
$guessedLetters[] = $guess;
if (strpos($wordToGuess, $guess) === false) {
$incorrectGuesses--;
}
if (str_replace(" ", "", displayWord($wordToGuess, $guessedLetters)) === $wordToGuess) {
echo "Congratulations! You guessed the word." . PHP_EOL;
break;
}
}
if ($incorrectGuesses === 0) {
displayHangman($incorrectGuesses);
echo "You ran out of guesses. The word was: " . $wordToGuess . PHP_EOL;
}
}
// Start the game
playHangman();

Ce code implémente un jeu du pendu où l'ordinateur choisit un mot aléatoire et le joueur doit deviner les lettres une par une. Le jeu affiche le dessin du pendu qui s'aggrave à chaque mauvaise réponse, et révèle progressivement les lettres correctes jusqu'à ce que le joueur gagne ou épuise ses 6 tentatives.

L'intelligence artificielle a réussi à comprendre l'objectif du script (un jeu du pendu) et a réécrit le code pour le rendre lisible. Non seulement le code est lisible, les noms de fonctions aussi, mais elle a également écrit des commentaires. Tout simplement incroyable !

L'obfuscation mise à part, si vous cherchez des outils plus classiques pour la qualité du code PHP, jetez un œil à l'image Docker qui regroupe les outils d'analyse statique.


Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?