PHP 之源代码加密与解密,加密后可直接运行
方式一:
<?php /** * Created by PhpStorm. * User: Yang * Date: 2019/10/16 * Time: 10:25 */ class Encipher { private $_sourceFile = ''; private $_encodedFile = ''; private $_comments = array( 'Author: Yang', 'Email: 1017836267@qq.com' ); public function __construct($sourceFile, $encodeFile, $comments = array()) { !empty($sourceFile) && $this->_sourceFile = $sourceFile; !empty($encodeFile) && $this->_encodedFile = $encodeFile; !empty($comments) && $this->comments = (array)$comments; if (empty($this->_sourceFile) || !file_exists($this->_sourceFile)) { exit("Source file does not exist."); } if (empty($this->_encodedFile) || !file_exists($this->_encodedFile)) { //如果源文件不存在,则创建 fopen($this->_encodedFile, "w"); } } /** * 返回随机字符串 * @return string */ private function createRandKey() { // 返回随机字符串 $str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; return str_shuffle($str); } /** * 加密函数 * @return bool */ public function encode() { //随机密匙1 $k1 = $this->createRandKey(); //随机密匙2 $k2 = $this->createRandKey(); // 获取源文件内容 $sourceContent = file_get_contents($this->_sourceFile); //base64加密 $base64 = base64_encode($sourceContent); //根据密匙替换对应字符。 $c = strtr($base64, $k1, $k2); $c = $k1 . $k2 . $c; $q1 = "O00O0O"; $q2 = "O0O000"; $q3 = "O0OO00"; $q4 = "OO0O00"; $q5 = "OO0000"; $q6 = "O00OO0"; $encodeContent = '$' . $q6 . '=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$' . $q1 . '=$' . $q6 . '{3}.$' . $q6 . '{6}.$' . $q6 . '{33}.$' . $q6 . '{30};$' . $q3 . '=$' . $q6 . '{33}.$' . $q6 . '{10}.$' . $q6 . '{24}.$' . $q6 . '{10}.$' . $q6 . '{24};$' . $q4 . '=$' . $q3 . '{0}.$' . $q6 . '{18}.$' . $q6 . '{3}.$' . $q3 . '{0}.$' . $q3 . '{1}.$' . $q6 . '{24};$' . $q5 . '=$' . $q6 . '{7}.$' . $q6 . '{13};$' . $q1 . '.=$' . $q6 . '{22}.$' . $q6 . '{36}.$' . $q6 . '{29}.$' . $q6 . '{26}.$' . $q6 . '{30}.$' . $q6 . '{32}.$' . $q6 . '{35}.$' . $q6 . '{26}.$' . $q6 . '{30};eval($' . $q1 . '("' . base64_encode('$' . $q2 . '="' . $c . '";eval(\'?>\'.$' . $q1 . '($' . $q3 . '($' . $q4 . '($' . $q2 . ',$' . $q5 . '*2),$' . $q4 . '($' . $q2 . ',$' . $q5 . ',$' . $q5 . '),$' . $q4 . '($' . $q2 . ',0,$' . $q5 . '))));') . '"));'; $headers = array_map('trim', array_merge(array('/*'), $this->_comments, array('*/'))); $enCode = "<?php"."\r\n".implode("\r\n", $headers) . "\r\n".$encodeContent."\r\n"."?>"; $file = fopen($this->_encodedFile, 'w'); return fwrite($file, $enCode) or die('写文件错误'); } } $e = new Encipher("index.php", "test_1.php"); $e ->encode(); echo "加密成功";
方式一改进版:
<?php /** * Created by PhpStorm. * User: Yang * Date: 2019/10/16 * Time: 10:25 */ class Encipher { private $c = ''; private $_sourceFile = ''; private $_targetFile = ''; private $_writeContent = ''; private $_comments = array( 'Author: Yang', 'Email: 1017836267@qq.com' ); public function __construct($sourceFile, $targetFile, $comments = array()) { !empty($sourceFile) && $this->_sourceFile = $sourceFile; !empty($targetFile) && $this->_targetFile = $targetFile; !empty($comments) && $this->comments = (array)$comments; if (empty($this->_sourceFile) || !file_exists($this->_sourceFile)) { exit("Source file does not exist."); } if (empty($this->_targetFile) || !file_exists($this->_targetFile)) { //如果源文件不存在,则创建 fopen($this->_targetFile, "w"); } $this->init(); } private function init() { $this->q1 = "O00O0O";//base64_decode $this->q2 = "O0O000";//$c(原文经过strtr置换后的密文,由 目标字符+替换字符+base64_encode(‘原文内容’)构成) $this->q3 = "O0OO00";//strtr $this->q4 = "OO0O00";//substr $this->q5 = "OO0000";//52 $this->q6 = "O00OO0";//urldecode解析过的字符串(n1zb/ma5\vt0i28-pxuqy*6%6Crkdg9_ehcswo4+f37j) } /** * 返回随机字符串 * @return string */ private function createRandKey() { // 返回随机字符串 $str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; return str_shuffle($str); } /** * 写入文件 * @param $targetFile 写入文件的路径 * @return $this */ private function write($targetFile) { $file = fopen($targetFile, 'w'); fwrite($file, $this->_writeContent) or die('写文件错误'); fclose($file); return $this; } /** * 对明文内容进行加密处理 * @param $sourceFile 要加密的文件路径 * @return $this */ private function encodeText($sourceFile) { //随机密匙1 $k1 = $this->createRandKey(); //随机密匙2 $k2 = $this->createRandKey(); // 获取源文件内容 $sourceContent = file_get_contents($sourceFile); //base64加密 $base64 = base64_encode($sourceContent); //根据密匙替换对应字符。 $c = strtr($base64, $k1, $k2); $this->c = $k1 . $k2 . $c; return $this; } private function encodeTemplate() { $encodeContent = '$' . $this->q6 . '=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$' . $this->q1 . '=$' . $this->q6 . '{3}.$' . $this->q6 . '{6}.$' . $this->q6 . '{33}.$' . $this->q6 . '{30};$' . $this->q3 . '=$' . $this->q6 . '{33}.$' . $this->q6 . '{10}.$' . $this->q6 . '{24}.$' . $this->q6 . '{10}.$' . $this->q6 . '{24};$' . $this->q4 . '=$' . $this->q3 . '{0}.$' . $this->q6 . '{18}.$' . $this->q6 . '{3}.$' . $this->q3 . '{0}.$' . $this->q3 . '{1}.$' . $this->q6 . '{24};$' . $this->q5 . '=$' . $this->q6 . '{7}.$' . $this->q6 . '{13};$' . $this->q1 . '.=$' . $this->q6 . '{22}.$' . $this->q6 . '{36}.$' . $this->q6 . '{29}.$' . $this->q6 . '{26}.$' . $this->q6 . '{30}.$' . $this->q6 . '{32}.$' . $this->q6 . '{35}.$' . $this->q6 . '{26}.$' . $this->q6 . '{30};eval($' . $this->q1 . '("' . base64_encode('$' . $this->q2 . '="' . $this->c . '";eval(\'?>\'.$' . $this->q1 . '($' . $this->q3 . '($' . $this->q4 . '($' . $this->q2 . ',$' . $this->q5 . '*2),$' . $this->q4 . '($' . $this->q2 . ',$' . $this->q5 . ',$' . $this->q5 . '),$' . $this->q4 . '($' . $this->q2 . ',0,$' . $this->q5 . '))));') . '"));'; $headers = array_map('trim', array_merge(array('/*'), $this->_comments, array('*/'))); $this->_writeContent = "<?php" . "\r\n" . implode("\r\n", $headers) . "\r\n" . $encodeContent . "\r\n" . "?>"; return $this; } /** * 获取解密后内容 * @param $sourceFileContent 解密前内容 * @return $this */ private function decodeTemplate($sourceFileContent) { //以eval为标志 截取为数组,前半部分为密文中的替换掉的函数名,后半部分为密文 $m = explode('eval',$sourceFileContent); //对系统函数的替换部分进行执行,得到系统变量 $varStr = substr($m[0],strpos($m[0],'$')); //执行后,后续就可以使用替换后的系统函数名 eval($varStr); //判断是否有密文 if(!isset($m[1])){ return $this; } //对密文进行截取 {$this->q4} substr $star = strripos($m[1],'('); $end = strpos($m[1],')'); $str = ${$this->q4}($m[1],$star,$end); //对密文解密 {$this->q1} base64_decode $str = ${$this->q1}($str); //截取出解密后的 核心密文 $evallen = strpos($str,'eval'); $str = substr($str,0,$evallen); //执行核心密文 使系统变量被赋予值 $O0O000 eval($str); $this->_writeContent = ${$this->q1}( ${$this->q3}( ${$this->q4}( ${$this->q2},${$this->q5}*2 ), ${$this->q4}( ${$this->q2},${$this->q5},${$this->q5} ), ${$this->q4}( ${$this->q2},0,${$this->q5} ) ) ); return $this; } /** * 加密函数 */ public function encode() { $this->encodeText($this->_sourceFile)->encodeTemplate()->write($this->_targetFile); echo 'encode-----解密前文件:'.$this->_sourceFile.'-----解密后文件:'.$this->_targetFile.'-----ok<br/>'; } /** * 解密函数 */ public function decode() { $sourceFileContent = file_get_contents($this->_sourceFile); $this->decodeTemplate($sourceFileContent)->write($this->_targetFile); echo 'decode-----解密前文件:'.$this->_sourceFile.'-----解密后文件:'.$this->_targetFile.'-----ok<br/>'; } } $e = new Encipher("login_2.php", "login_3.php"); $e->encode(); $e = new Encipher("login_3.php", "login_4.php"); $e->decode();
批量加密解密没有做
方式二:
require_once "./doEncode.php"; $app = str_replace('\\', '/', dirname(__FILE__)); $encipher = new DoCodeLock($app."/test", $app."/test"); $encipher->encode();
doEncode.php
<?php /** * Created by PhpStorm. * User: 25754 * Date: 2019/10/16 * Time: 9:32 */ class DoCodeLock { /** * The file/path which you want to encode. */ public $source_file = ''; /** * The file/path which you want to save the encoded file/path. */ public $encoded_file = ''; /** * Default comments. */ public $comments = array( 'Author: Yang', 'Email: 1017836267@qq.com' ); /** * advanced encryption */ public $advancedEncryption = false; /** * variable name length. */ public $varnameLength = 8; public function __construct($source_file = '', $encoded_file = '', $comments = array()) { !empty($source_file) && $this->source_file = $source_file; !empty($encoded_file) && $this->encoded_file = $encoded_file; !empty($comments) && $this->comments = (array)$comments; if (empty($this->source_file) || !file_exists($this->source_file)) { exit("Source file/path does not exist."); } if (empty($this->encoded_file) || !file_exists($this->encoded_file)) { exit("Encoded file/path does not exist."); } } public function encode() { list($paths, $files) = $this->_getPathsAndFiles($this->source_file); $this->_createPaths($paths); $this->_encryptFiles($files); } private function _getPathsAndFiles($dir) { $files = $paths = array(); if (is_dir($dir)) { $_files = scandir($dir); foreach ($_files as $key => $file) { if ($file == '.' || $file == '..') { continue; } if (is_dir($dir . "/" . $file)) { $paths[] = $file; list($subPaths, $subFiles) = $this->_getPathsAndFiles($dir . "/" . $file); $subPaths = $this->_addBasePath($subPaths, $file); $subFiles = $this->_addBasePath($subFiles, $file); $paths = array_merge($paths, $subPaths); $files = array_merge($files, $subFiles); } else { $files[] = $file; } } } elseif (is_file($dir)) { $files[] = basename($dir); } return array($paths, $files); } private function _addBasePath($files, $base) { foreach ($files as $key => $file) { $files[$key] = $base . "/" . $file; } return $files; } private function _createPaths($paths) { foreach ($paths as $path) { !is_dir($this->encoded_file . "/" . $path) && mkdir($this->encoded_file . "/" . $path, 0700); } } private function _encryptFiles($files) { foreach ($files as $file) { if ($this->advancedEncryption) { $this->_encryptFile($file); } else { $this->_setHumanUnreadable($file); } } } private function _setHumanUnreadable($file) { $code = $this->_getPHPCode($file); $regVars = $this->_setVarName($this->_getMatchedVariables($code)); list($usedFuncs, $funcChars) = $this->_getMatchedFunctions($code); if (!empty($usedFuncs)) { $_tmp = $this->_setVarName(array('funcStrVar' => ''), $regVars); $funcStrVar = $_tmp['funcStrVar']; $usedFuncMaps = $this->_setVarName($usedFuncs, $regVars); $regVars = array_merge($usedFuncMaps, $regVars); } else { $usedFuncMaps = array(); } $funcVarDefCode = $this->_getFuncVarDefCode($usedFuncMaps, $funcChars, $funcStrVar); $headers = array_map('trim', array_merge(array('<?php', '/*'), $this->comments, array('*/'))); $enCode = implode("\r\n", $headers) . "\r\n" . $funcVarDefCode . strtr($code, $regVars); $this->_saveEncryptFile($file, $enCode); } private function _encryptFile($file) { list($enkey, $dekey) = $this->_getKeyPairs(); $baseCodeOfHostedCode = $this->_getBaseCodeOfHostedCode(); $decodeCodeOfHostedCode = $this->_getDecodeCodeOfHostedCode($file, $enkey, $dekey); $hostedCode = $baseCodeOfHostedCode . $decodeCodeOfHostedCode; $regVars = $this->_setVarName($this->_getMatchedVariables($hostedCode)); list($usedFuncs, $funcChars) = $this->_getMatchedFunctions($hostedCode); if (!empty($usedFuncs)) { $_tmp = $this->_setVarName(array('funcStrVar' => ''), $regVars); $funcStrVar = $_tmp['funcStrVar']; $usedFuncMaps = $this->_setVarName($usedFuncs, $regVars); $regVars = array_merge($usedFuncMaps, $regVars); } else { $usedFuncMaps = array(); } //$prefixCode: define function name & base extra code. $funcVarDefCode = $this->_getFuncVarDefCode($usedFuncMaps, $funcChars, $funcStrVar); $prefixCode = preg_replace("/\r|\n|\s+/is", "", $funcVarDefCode . strtr($baseCodeOfHostedCode, $regVars)); $headers = array_map('trim', array_merge(array('<?php', '/*'), $this->comments, array('*/'))); $hookKey = strtr(md5(implode("\r\n", $headers) . "\r\n" . $prefixCode), $enkey, $dekey); $evalEmbedCode = $this->_getEvalEmbedCode($decodeCodeOfHostedCode, $regVars, $enkey, $dekey); /** * eval(base64_decode( * str_replace("\$hookKey", '', strtr($hookKey.$evalEmbedCode, $dekey, $enkey)) * )); * $unset; */ $unset = 'unset(' . $funcStrVar; foreach ($regVars as $var) { $unset .= ',' . $var; } $unset .= ');'; $evalCode = "@eval(" . $regVars["base64_decode"] . "(" . $regVars["str_replace"] . "(" . $regVars["\$hookKey"] . ",''," . $regVars["strtr"] . "('" . $hookKey . $evalEmbedCode . "','" . $dekey . "','" . $enkey . "'))));" . $unset; $originalEncodedCode = $this->_getPHPEncode($file, $enkey, $dekey); $enCode = implode("\r\n", $headers) . "\r\n" . $prefixCode . $evalCode . "return;?>\r\n" . $originalEncodedCode; $this->_saveEncryptFile($file, $enCode, $enkey, $dekey); } /** * The encoded code needs extra code */ private function _getBaseCodeOfHostedCode() { $code = <<<EOT \$farrs = file(str_replace('\\\\', '/', __FILE__)); \$enCode = array_pop(\$farrs); \$phpCode = array_pop(\$farrs); \$fstrs = implode('', \$farrs) . substr(\$phpCode, 0, strrpos(\$phpCode, '@ev')); \$hookKey = md5(\$fstrs); \$farrs = \$phpCode = \$fstrs = NULL; EOT; return $code; } /** * The encoded code needs decode code * if the licence is generated, also need to process it. */ private function _getDecodeCodeOfHostedCode($file, $enkey, $dekey) { $code = <<<EOT eval(base64_decode(strtr(\$enCode, '{$dekey}', '{$enkey}'))); \$enCode = NULL; EOT; return $code; } private function _getFuncVarDefCode($usedFuncMaps, $funcChars, $funcStrVar) { //all the chars of function name $funcStr = implode("", $funcChars); //set variable name's value for each variable of function name $funcVarValArr = $this->_getFuncVarvalArr($usedFuncMaps, $funcChars, $funcStrVar); //encoded code define function name string. $code = $funcStrVar . "='{$funcStr}';"; foreach ($usedFuncMaps as $func => $val) { $code .= $val . "= " . $funcVarValArr[$func] . ";\n"; } return $code; } private function _getEvalEmbedCode($decodeCodeOfHostedCode, $regVars, $enkey, $dekey) { $code = preg_replace("/\r|\n/is", "", strtr($decodeCodeOfHostedCode, $regVars)); //replace multi space to one, and encode it via base64 $code = base64_encode(preg_replace("/\s{2,}/is", " ", $code)); $code = strtr($code, $enkey, $dekey); return $code; } /** * get function names and chars for all functions */ private function _getMatchedFunctions($code) { //match all function name preg_match_all("/([a-z_0-9]+)\(/is", $code, $matches); $usedFuncs = array_unique($matches[1]); if (false !== ($key = array_search('eval', $usedFuncs))) { unset($usedFuncs[$key]); } $funcChars = array_unique(preg_split("//is", implode("", $usedFuncs), -1, PREG_SPLIT_NO_EMPTY)); shuffle($funcChars); return array(array_flip($usedFuncs), $funcChars); } /** * get variable names */ private function _getMatchedVariables($code) { preg_match_all("/(\\\$[a-z0-9]+)\s*\=/is", $code, $matches); return array_flip($matches[1]); } private function _getFuncVarvalArr($usedFuncMaps, $funcChars, $funcStrVar) { $funcVarValArr = array(); foreach ($usedFuncMaps as $func => $_val) { $val = ""; for ($i = 0, $len = strlen($func); $i < $len; $i++) { if ($val == "") { $val = $funcStrVar . "{" . array_search($func{$i}, $funcChars) . "}"; } else { $val = $val . "." . $funcStrVar . "{" . array_search($func{$i}, $funcChars) . "}"; } } $funcVarValArr[$func] = $val; } return $funcVarValArr; } /** * get php pure code, trim php tag */ private function _getPHPCode($file) { $from = $this->source_file . '/' . $file; $str = file_get_contents($from); $str = preg_replace("/^[\s\xef\xbb\xbf]*<\?php/is", "", $str); $str = trim(preg_replace("/\?>\s*$/is", "", $str)); return $str; } /** * get php encoded code */ private function _getPHPEncode($file, $enkey, $dekey) { $code = $this->_getPHPCode($file); $enCode = strtr(base64_encode($code), $enkey, $dekey); return $enCode; } private function _getKeyPairs() { $enkey = $this->_getKeyStr(); $dekey = $this->_getKeyStr(); while ($enkey === $dekey) { $dekey = $this->_getKeyStr(); } return array($enkey, $dekey); } private function _getKeyStr() { $base64str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; for ($i = 127; $i <= 160; $i++) { $base64str .= chr($i); } $baseChars = array_filter(preg_split("//is", $base64str)); $baseChars[] = 0; shuffle($baseChars); return implode("", $baseChars); } private function _setVarName($funcs, $filter = array()) { $length = $this->varnameLength; $basestr = $this->_getInvisibleStr($length); $count = count($funcs); if ($count == 0) { return array(); } $varArr = array(); do { $randStr = substr("\$" . str_shuffle($basestr), 0, rand(2, $length)); if (!in_array($randStr, $varArr) && !in_array($randStr, $filter)) { $varArr[] = $randStr; $count--; } } while ($count > 0); return array_combine(array_keys($funcs), $varArr); } /** * legal variable names: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' * Invisiable string's ascii is from 127 to 255:'[\x7f-\xff][\x7f-\xff]*' * param $length the variable name's length. */ private function _getInvisibleStr($length = 10) { $str = ''; for ($i = 0; $i < $length; $i++) { $num = rand(127, 255); $str .= chr($num); } return $str; } private function _saveEncryptFile($file, $enCode, $enkey = null, $dekey = null) { $to = $this->encoded_file . '/' . $file; file_put_contents($to, $enCode); echo $to . "\n"; } }