<?php
#
# Generic php deobfuscator. Caveat emptor.  This will verbosely
# run code that you have not seen and which you should not trust.
# By the time you see what it is doing, it is too late.

# Usage:
#    sudo useradd -m unsafe
#    sudo iptables -I OUTPUT -m owner --uid-owner unsafe -j LOG
#    sudo iptables -I OUTPUT -m owner --uid-owner unsafe -j DROP
#    sudo -u unsafe -c 'php deobfuscate.php evilscript.php'
#    ps uaxw|grep ^unsafe|awk '{print $2}'|sudo xargs kill -9
#
# ie. run it as another user (unsafe) and hope that it doesn't
# hit you with a privilege escalation, or something that phones
# home by some side channel.  If you don't know what that means
# then the correct usage is this:

# Usage:
#    rm deobfuscate.php

if (isset($_SERVER['HTTP_HOST'])) {
    
$f=file_get_contents($_SERVER["SCRIPT_FILENAME"]);
    if (isset(
$_GET['html'])) {
        
header("Content-type: text/html");
        echo 
highlight_string($f); die();
    } 
    else {
        
header("Content-type: text/plain");
        echo 
$f; die();
    }
    die();
}

# Override die() and other functions
function DIEANOTHERDAY($reason=''){
 echo 
"\n// -- Not dying: \"$reason\" --\n";
}
function 
UN_system($parameters){ echo "\n// -- skipping \"system($parameters);\" --\n"; }
function 
UN_passthru($parameters){ echo "\n// -- skipping \"passthru($parameters);\" --\n"; }
function 
UN_shell_exec($parameters){ echo "\n// -- skipping \"shell_exec($parameters);\" --\n"; }
# Include by eval
function UN_include($f1l3n4m3){
        print 
"\n// -- include file $f1l3n4m3 --\n";
        return 
ev41("?>".file_get_contents($f1l3n4m3));
}
function 
ev41($evalcode){
    global 
$allvarnames$obfuscation$deobf_be_verbose;
    
$obfuscation+=1;
    if (
$obfuscation>0) {
        print 
"\n//--- begin $obfuscation ---\n".$evalcode."\n//--- end $obfuscation ---\n\n";
    }
    
# Make anything that looks like a variable global
    
preg_match_all ('/\$([a-zA-Z_]\w*)/'$evalcode$varnames0);
    foreach (
$varnames[0] as $varname) {
        
# echo "var $varname"; print_r($varname); echo "\n";
        
$allvarnames[$varname]=1;
    }
    
$export_global='';
    foreach (
$allvarnames as $varname => $blah) { 
        
$export_global .= 'global '.$varname.";\n";
    }
    
    
#$GLOBAL['evalcode']=$evalcode;
    #foreach ($GLOBALS as $key => $val) { global $$key; }  /* import the global namespace .. eish */
    #$excludeList = array('GLOBALS', '_FILES', '_COOKIE', '_POST', '_GET', 'excludeList');
    #$export_global="\n".
    #    '$vars_defined=array_diff(get_defined_vars(),$excludeList);'."\n".
    #    'foreach ($vars_defined as $name_11 => $value_11) { echo "$name_11 "; $GLOBALS[$name_11]=$value_11; } '."\n";
    
global $argv1;
    
$evalcode preg_replace('/\b(include|include_once|require|require_once)\b/''UN_include'$evalcode );
    
$evalcode preg_replace('/\beval\b/'"ev41"$evalcode );
    
$evalcode preg_replace('/\bdie\b/'"DIEANOTHERDAY"$evalcode );
    
$evalcode preg_replace('/\bsystem\b/'"UN_system"$evalcode );
    
$evalcode preg_replace('/\bpassthru\b/'"UN_passthru"$evalcode );
    
$evalcode preg_replace('/\bshell_exec\b/'"UN_shell_exec"$evalcode );
    
$evalcode preg_replace('/\b__FILE__\b/''"'.$argv1.'"'$evalcode );
    
$evalcode preg_replace('/;/'";\n"$evalcode ); # better layout
    
$evalcode $export_global.$evalcode;
    if (
$deobf_be_verbose==1) {
        echo 
"// This is what we're really running ...\n$evalcode\n";
    }
    eval(
$evalcode);
    
#foreach ($allvarnames as $varname => $blah) { 
    #    $snippet = substr($GLOBAL[substr($varname,1,999)],0,32);
    #    echo $varname."=$snippet\n";
    #}
}

// Close stdin
fclose(fopen("php://stdin","r"));

$deobf_be_verbose 0;
foreach (
$argv as $argv1) {
    if (
$argv1==$argv[0]) { continue; }
    if (
$argv1=="-v") { $deobf_be_verbose=1; continue; }
    
$obfuscation=-1;
    echo 
"\n// -- file ".$argv1." --\n";
    
$filecode="?>".file_get_contents($argv1);
    
$allvarnames=array();
    
ev41($filecode);
    echo 
"\n";
}

1