├── README.md ├── example.php ├── obfuscator.packed.php ├── obfuscator.php └── to_pack.php /README.md: -------------------------------------------------------------------------------- 1 | PHP Obfuscator 0.1 2 | ============================================================================= 3 | *This script is in it's very beginning stages. Report any bugs you may find.* 4 | 5 | Usage 6 | ----------------------------------------------------------------------------- 7 | Refer to 'examples.php' included with the script. 8 | -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | file('to_pack.php'); 11 | 12 | // $packer->strip=false; // Turn off stripping whitespace. 13 | // $packer->strip_comments=false; // Turn off stripping comments (Automatically enabled by $strip. Enabling $strip will override this.) 14 | // $packer->b64=false; // Turn off base64 passover. 15 | 16 | // Run the packer 17 | $packer->pack(); 18 | 19 | // Echo the code. 20 | echo $packer->code(); 21 | 22 | // Or save the code.. 23 | // if ($packer->save('packed.php')) echo "Saved file.\n"; 24 | 25 | // Or you can chain functions together. 26 | // echo $packer->file('to_pack.php')->pack()->code(); 27 | 28 | ?> 29 | -------------------------------------------------------------------------------- /obfuscator.packed.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /obfuscator.php: -------------------------------------------------------------------------------- 1 | algos=hash_algos(); 24 | return $this; 25 | } 26 | 27 | public function file($file) { 28 | if (file_exists($file)) $this->code=file_get_contents($file); 29 | return $this->tokenize(); 30 | } 31 | 32 | public function code($text=null) { 33 | if (empty($text)) return $this->code; 34 | $this->code=$text; 35 | return $this->tokenize(); 36 | } 37 | 38 | public function save($file) { 39 | if (!empty($this->code)) if (@file_put_contents($file,$this->code)) return true; 40 | return false; 41 | } 42 | 43 | private function random_string() { 44 | $number=round((mt_rand(1,mt_rand(1000,10000))*mt_rand(1,10))/mt_rand(1,10)); 45 | if (!empty($this->algos)) $algo=$this->algos[mt_rand(0,(count($this->algos)-1))]; 46 | $hash=hash($algo,$number); 47 | return $hash; 48 | } 49 | 50 | private function encode($tmp) { 51 | if ($this->strip) $tmp=preg_replace('/[\n\t\s]+/',' ',$tmp); 52 | $tmp=preg_replace('/^\<\?(php)*/','',$tmp); 53 | $tmp=preg_replace('/\?\>$/','',$tmp); 54 | $tmp=str_replace(array('\"','$','"'),array('\\\"','\$','\"'),$tmp); 55 | $tmp=trim($tmp); 56 | if ($this->b64) { 57 | $tmp=base64_encode("$tmp"); 58 | $tmp="\n"; 59 | } else $tmp="\n"; 60 | $this->code=$tmp; 61 | } 62 | 63 | private function encode_string($text) { 64 | for ($i=0;$i<=strlen($text)-1;$i++) { 65 | $chr=ord(substr($text,$i,1)); 66 | if ($chr==32||$chr==34||$chr==39) $tmp[]=chr($chr); // Space, leave it alone. 67 | elseif ($chr==92&&preg_match('/\\\(n|t|r|s)/',substr($text,$i,2))) { 68 | // New line, leave it alone, and add the next char with it. 69 | $tmp[]=substr($text,$i,2); 70 | $i++; // Skip the next character. 71 | } 72 | else $tmp[]='\x'.strtoupper(base_convert($chr,10,16)); 73 | } 74 | if (!empty($tmp)) $text=implode('',$tmp); 75 | return $text; 76 | } 77 | 78 | private function generate_var($var,$function=null,$class=null) { 79 | while (empty($string)) { 80 | $string="\$_{$this->random_string()}"; 81 | if (empty($function)&&empty($class)) { 82 | if (!empty($this->_globals[$var])) return $this->_globals[$var]; 83 | else { 84 | if (in_array($string,$this->_globals)) $string=null; 85 | else $this->_globals[$var]=$string; 86 | } 87 | } 88 | elseif (!empty($function)&&empty($class)) { 89 | if (!empty($this->_functions[$var])) return $this->_functions[$var]; 90 | else { 91 | if (in_array($string,$this->_functions)) $string=null; 92 | else $this->_functions[$var]=$string; 93 | } 94 | } 95 | elseif (!empty($function)&&!empty($class)) { 96 | if (!empty($this->_classes[$class]['functions'][$function][$var])) return $this->_classes[$class]['functions'][$function][$var]; 97 | else { 98 | if (!empty($this->_classes[$class]['functions'][$function])&&in_array($string,$this->_classes[$class]['functions'][$function])) $string=null; 99 | else $this->_classes[$class]['functions'][$function][$var]=$string; 100 | } 101 | } 102 | elseif (empty($function)&&!empty($class)) { 103 | if (!empty($this->_classes[$class]['globals'][$var])) return $this->_classes[$class]['globals'][$var]; 104 | else { 105 | if (!empty($this->_classes[$class]['globals'])&&in_array($string,$this->_classes[$class]['globals'])) $string=null; 106 | else $this->_classes[$class]['globals'][$var]=$string; 107 | } 108 | } 109 | } 110 | return $string; 111 | } 112 | 113 | public function pack() { 114 | if (empty($this->tokens)) return false; 115 | foreach ($this->tokens as $token_key=>&$token) { 116 | if (is_array($token)) { 117 | switch ($token[0]) { 118 | case T_FUNCTION: 119 | if ($this->tokens[$token_key-2][0]==T_VARIABLE) $this->function=$this->tokens[$token_key-2][1]; 120 | elseif ($this->tokens[$token_key+2][0]==T_STRING) $this->function=$this->tokens[$token_key+2][1]; 121 | break; 122 | case T_CLASS: 123 | $this->class=$this->tokens[$token_key+2][1]; 124 | break; 125 | case T_VARIABLE: 126 | if ($token[1]=='$this') break; // Absolutely skip $this. 127 | if (in_array($token[1],$this->skip_variables)) { 128 | // Skip renaming anything that should be ignored, but encode it so that it's not in plaintext. 129 | $token[1]="\${$this->encode_string(substr($token[1],1))}"; 130 | break; 131 | } 132 | if (!empty($this->tokens[$token_key-1][1])&&$this->tokens[$token_key-1][0]==T_DOUBLE_COLON) break; // Static class variable. Don't touch it. 133 | if (!empty($this->tokens[$token_key-2][1])&&$this->tokens[$token_key-2][0]==T_GLOBAL) { 134 | if ($this->function) 135 | if ($this->class) $token[1]=$this->_vars['classes'][$this->class][$this->function][$token[1]]=$this->generate_var($token[1]); 136 | else $token[1]=$this->_vars['functions'][$this->function][$token[1]]=$this->generate_var($token[1]); 137 | elseif ($this->class) die("\nPHP syntax error found. Exiting.\n"); 138 | } 139 | elseif ($this->function) { 140 | if ($this->class) { 141 | if (!empty($this->_vars['classes'][$this->class][$this->function][$token[1]])) $token[1]=$this->_vars['classes'][$this->class][$this->function][$token[1]]; 142 | else $token[1]=$this->generate_var($token[1],$this->function,$this->class); 143 | } 144 | else { 145 | if (!empty($this->_vars['functions'][$this->function][$token[1]])) $token[1]=$this->_vars['functions'][$this->function][$token[1]]; 146 | else $token[1]=$this->generate_var($token[1],$this->function); 147 | } 148 | } 149 | elseif ($this->class) { 150 | $token[1]=$this->generate_var($token[1],null,$this->class); 151 | } 152 | else { 153 | $token[1]=$this->generate_var($token[1]); 154 | } 155 | break; 156 | case T_OBJECT_OPERATOR: 157 | if ($this->tokens[$token_key-1][1]=='$this'&&$this->function&&$this->class) { 158 | $this->tokens[$token_key-1][1]='$'.$this->encode_string('this'); 159 | if ($this->tokens[$token_key+2]=='('); // Function, encode $this and leave it alone. 160 | else $this->tokens[$token_key+1][1]=substr($this->generate_var("\${$this->tokens[$token_key+1][1]}",null,$this->class),1); 161 | } else die("\nPHP syntax error found: \$this referenced outside of a class.\n"); 162 | break; 163 | case T_DOUBLE_COLON: 164 | if ($this->tokens[$token_key-1][1]=='$this') { 165 | if ($this->function&&$this->class) { 166 | $this->tokens[$token_key-1][1]='$'.$this->encode_string('this'); 167 | if ($this->tokens[$token_key+2]=='('); // Function, leave it alone. 168 | else $this->tokens[$token_key+1][1]=$this->generate_var($this->tokens[$token_key+1][1],null,$this->class); 169 | } else die("\nPHP syntax error found: \$this referenced outside of a class.\n"); 170 | } else { 171 | if ($this->tokens[$token_key+2]=='('); // Function, leave it alone. 172 | else $this->tokens[$token_key+1][1]=$this->generate_var($this->tokens[$token_key+1][1],null,$this->tokens[$token_key-1][1]); 173 | } 174 | break; 175 | case T_COMMENT: 176 | case T_DOC_COMMENT: 177 | case T_ML_COMMENT: // Will be equal to T_COMMENT if not in PHP 4. 178 | if ($this->strip_comments||$this->strip) $token[1]=''; 179 | break; 180 | case T_START_HEREDOC: 181 | // Automatically turn whitespace stripping off, because formatting needs to stay the same. 182 | $this->strip=false; 183 | break; 184 | case T_END_HEREDOC: 185 | $token[1]="\n{$token[1]}"; 186 | break; 187 | case T_CURLY_OPEN: 188 | case T_DOLLAR_OPEN_CURLY_BRACES: 189 | case T_STRING_VARNAME: 190 | if ($this->function) $this->depth++; 191 | break; 192 | } 193 | } else { 194 | switch ($token) { 195 | case '{': 196 | if ($this->function) $this->depth++; 197 | break; 198 | case '}': 199 | $this->depth--; 200 | if ($this->depth<0) $this->depth=0; 201 | if ($this->function&&$this->depth==0) { 202 | $_functions=array(); // Empty function variables array 203 | $this->_vars['functions']=array(); // Empty any temp variables 204 | $this->function=false; 205 | } 206 | elseif ($this->class&&$this->depth==0) { 207 | $this->_vars['classes']=array(); // Empty any temp variables 208 | $this->class=false; 209 | } 210 | break; 211 | } 212 | } 213 | } 214 | $this->detokenize(); 215 | return $this; 216 | } 217 | 218 | private function tokenize() { 219 | if (empty($this->code)) return false; 220 | $this->tokens=token_get_all($this->code); 221 | return $this; 222 | } 223 | 224 | private function detokenize() { 225 | if (empty($this->tokens)) return; // No tokens to parse. Exit. 226 | foreach ($this->tokens as &$token) { 227 | if (is_array($token)) { 228 | switch ($token[0]) { 229 | // Looks like overkill, but helpful when extending to encode certain things differently. 230 | case T_INCLUDE: 231 | case T_INCLUDE_ONCE: 232 | case T_REQUIRE: 233 | case T_REQUIRE_ONCE: 234 | case T_STATIC: 235 | case T_PUBLIC: 236 | case T_PRIVATE: 237 | case T_PROTECTED: 238 | case T_FUNCTION: 239 | case T_CLASS: 240 | case T_EXTENDS: 241 | case T_GLOBAL: 242 | case T_NEW: 243 | case T_ECHO: 244 | case T_DO: 245 | case T_WHILE: 246 | case T_SWITCH: 247 | case T_CASE: 248 | case T_BREAK: 249 | case T_CONTINUE: 250 | case T_ENDSWITCH: 251 | case T_CONST: 252 | case T_DECLARE: 253 | case T_ENDDECLARE: 254 | case T_FOR: 255 | case T_ENDFOR: 256 | case T_FOREACH: 257 | case T_ENDFOREACH: 258 | case T_IF: 259 | case T_ENDIF: 260 | case T_RETURN: 261 | case T_UNSET: 262 | case T_EXIT: 263 | case T_VAR: 264 | case T_STRING: 265 | case T_ENCAPSED_AND_WHITESPACE: 266 | case T_CONSTANT_ENCAPSED_STRING: 267 | $token[1]=$this->encode_string($token[1]); 268 | break; 269 | } 270 | $tmp[]=$token[1]; 271 | } 272 | else $tmp[]=$token; 273 | } 274 | $tmp=implode('',$tmp); 275 | $this->encode($tmp); 276 | } 277 | 278 | } 279 | 280 | ?> 281 | -------------------------------------------------------------------------------- /to_pack.php: -------------------------------------------------------------------------------- 1 | test = "Testing"; 25 | $test="Testing4"; 26 | $this->test("Testing 5.."); 27 | } 28 | static function test($msg) { echo "Message: $msg\n"; } 29 | } 30 | 31 | 32 | test("Testing1","Testing2"); 33 | test::test("Testing3"); 34 | echo "{$test}\n"; 35 | $test=new test(); 36 | $msg("Testing5"); 37 | 38 | echo "\n"; // New line for dump 39 | 40 | var_dump($test,$msg); 41 | 42 | ?> 43 | --------------------------------------------------------------------------------