PHP Verschlüsselung ala Code Eclipse

Ist man nicht gerade im Open Source Umfeld tätig, spielt der Schutz des Know Hows bei der Auslieferung von eigener Software eine große Rolle.
Besonders schwierig wird dies bei der Verwendung von Scriptsprachen, die per Definition nicht kompiliert, sondern zur Laufzeit interpretiert werden und somit als reiner Sourcecode für den Interpreter vorliegen. Sicherlich gibt es Lösungen, z.B. von Zend, die mit “modifizierten” Interpretern auch eine Verschlüsselung des Quellcodes ermöglichen. Nutzt man jedoch den Standard Interpreter wird das ganze schon etwas kniffliger.

Die Website http://www.codeeclipse.com/ ermöglich das kostenlose “verschlüsseln” von PHP Code und wirbt dabei mit dem Slogan “Complete protection, total compatibility!”Zum Beweis ein kleines PHP Snippet und das Ergenis von Code Eclipse:

function print_hello_world($username)
{
echo "Hello $username";
}

$name = $_REQUEST['name'];
if ($name == "Administrator")
{
echo "Secret";
}
else
{
print_hello_world( $name );
}
/*******************************************\
|  Source code obfuscated  by Code Eclipse  |
|        http://www.codeeclipse.com/        |
| Complete protection, total compatibility! |
\*******************************************/

function print_hello_world($x0b){ global $;  echo "\x48\145\x6c\x6c\157\040$x0b";}
$x0c = $_REQUEST['name'];if ($x0c == "Ad\155i\156i\x73t\x72\141\164\x6f\162")
{ echo "\123\145\143\162\x65\164";}else{print_hello_world( $x0c );}

Mann muss zugestehen, dass in meinem Beipiel noch recht deutlich die ursprünglichen Funktionsaufrufe zu erkennen sind. Bei umfangreicherem Quellcode viel mir das auf den ersten Blick jedoch nicht  ganz so leicht. Dass der Code noch 1:1 so funktioniert stimmt. Es stellt sich also die Frage, wie der Interpreter ohne Wissen über die “angebliche Verschlüsselung” zu kennen, in der Lage ist den Quellcode auszuführen.

Die Antwort lautet natürlich: Der Quellcode ist in keiner Form verschlüsselt. Er wurde lediglich für das menschliche Auge unleserlich gestaltet. Hier also nun der Versuch die “Verunstaltung” des Codes rückgängig zu machen.

1.) Umbenennung von Variablen

Unser ursprünglicher Parameter der Funktion hieß “$username”. Dieser wurde vom Obfuscator in “$x0b” umbenannt. Dies lässt sich zwar nicht wieder umkehren da der Ursprungswert verloren ist, allerdings reicht hier ein manuelles “Suchen & Ersetzen” sobald ein sinnhafter Name für diese Funktion identifiziert ist aus um den Code wieder leserlich zu gestalten.

2.) Zeilenumbrüche entfernen

Auch dies ist lediglich eine kleine Hürde bedenkt man die “Auto-Format” Funktion vieler moderner IDE’s.

3.) Umwandlung von Zeichenketten

Was auf den ersten Blick als wirklich “verschlüsselt” aussieht, sind die zahlreichen kryptischen Zahlen, z.B. “\x48\145\x6c\x6c\157\040$x0b”. Tatsächlich verstecken sich dahinter lediglich zwei andere Darstellungsformen der für uns lesbaren Zeichen, nämlich eine Hex- und eine Oktan- Schreibweise. Somit wird aus “\x48″, welches den Hexadezimalwert 48 darstellt, ein Dezimalwert von 72. In der ASCII Tabelle steht für 72 das Zeichen “H”. Das Zeichen \145 wird bei der Umwandlung von oktal zu dezimal Schreibweise zu einer 101, was dem Buchstaben “e” entspricht.
Nach dem selben Verfahren werden durch den Obfuscator auch Steuerzeichen wie Zeilenumbruch oder Tabs ersetzt, was den Code weiter verunstaltet.

Mit diesem Wissen lässt sich der Code natürlich auch wieder in lesbaren ASCII Code wandeln. Ich habe mich in diesem Fall für ein kleines Ruby entschieden. Klein deshalb, weil tatsächlich 4 Zeilen Code ausreichen:

f = IO.readlines( $ARGV[1] ).join

f.gsub!( /\\x([0-9a-f]{2})/ ){|pa| $1.hex.chr }
f.gsub!( /\\([0-9]{3})/ ){|pa| $1.oct.chr }

File.open( "new.#{$ARGV[1]}", "w+" ){ |t| t << f }

Ergebnis

function print_hello_world($x0b){ global $;  echo "Hello $x0b";}
$x0c = $_REQUEST['name'];if ($x0c == "Administrator")
{ echo "Secret";}else{print_hello_world( $x0c );}

Schickt man das ganze nun noch durch einen Auto-Layouter einer IDE kommt man dem Original schon sehr nahe.

function print_hello_world($x0b)
{
global $;
echo "Hello $x0b";
}
$x0c = $_REQUEST['name'];
if ($x0c == "Administrator")
{
echo "Secret";
}
else
{
print_hello_world( $x0c );
}

Eins sollte hier allerdings noch erwähnt werden: Bei näherer Betrachtung sieht man bereits im komplett verschlüsselten Code den Aufruf “global $;”. Dieser war in meinem Original Quellcode nicht vorhanden und wurde offensichtlich durch den Obfuscator eingefügt. Neben der unzulänglichen Verschlüsselung wird also zudem noch in den Code eingegriffen, was aus meiner Sicht höchst kritisch ist. Gerade aus der Sicherheits-Perspektive finde ich die globale Übergabe aller Variablen im aktuellen Scope an die Funktion höchst fragwürdig…

Schlagworte: , , , , ,

Kommentieren