目录
复制代码
screw plus
是一个开源的php
扩展,作用是对php
文件进行加密,网络上提供php
加密的服务很多,但大多都只是混淆级别的加密,被人拿到加密文件问只要有足够耐心就能破解,与之不同的是,screw plus
采用扩展来加解密,而且是全球金融业流行的高强度AES256
加密,除非破解了服务器,否则黑客拿到了加密文件也只是一堆乱码。
同一个加密级别的有ioncube
和官方的zend guard
,但这两款都是收费的,一年至少数千元的费用并不值得普通开发者去尝试,而使用screw plus
,你不需要多花一分钱。
下面以LNMP一键安装环境为例演示下screw plus
的配置
首先克隆一份代码到服务器
git clone https://git.oschina.net/splot/php-screw-plus.git
编译PHP解密扩展
进入项目目录,然后执行php
的phpize
文件,phpize
是官方提供的可执行文件用于动态生成扩展开发环境,一般在php
的bin
目录下可以找到。lnmp
的phpize
在/usr/local/php/bin/phpize
/usr/local/php/bin/phpize
Configuring for:
PHP Api Version: 20100412
Zend Module Api No: 20100525
Zend Extension Api No: 220100525
执行成功后可以看到当前的php api版本,扩展api版本等。下一步就可以开始配置了。配置命令为
./configure --with-php-config=[php-config]
, [php-config]
一般也在php的bin目录下,写绝对路径就可以了。
./configure --with-php-config=/usr/local/php/bin/php-config
如果没报错,说明配置成功了,可以开始下一步编译了。
编译之前,我们可以修改加密的key
,打开php_screw_plus.h
可以看到开头就是 #define CAKEY "..."
,把里面的值改为一个足够复杂的key
,最好16位以上,比如:9mqss6q7WsBpTMOZ
vi php_screw_plus.h
修改完毕之后,直接开始编译,执行make命令,如果最后显示Build complete.说明编译成功,扩展在modules里面,如果报错请根据提示进行修复,然后make clean
之后重新编译。
make
...
Build complete.
然后需要把扩展的路径加入到php.ini
中,你可以把modules/php_screw_plus.so
复制到php扩展目录也可以直接在ini中加入绝对路径,我一般倾向于绝对路径这样修改编译了扩展也不需要重新复制过去。
vi php/etc/php.ini
加入绝对路径例如
extension=/home/php_screw_plus-1.0/modules/php_screw_plus.so
然后重启php
服务 这时可以放个php
文件输出phpinfo
信息,如果看到以下提示说明扩展生效了。
编译加密工具
上面我们编译的是解密程序,而加密程序也需要我们手动编译一下,进入tools
目录执行make
命令即可。如果没有报错,则扩展就全部编译完成了。
cd tools/
make
(Anna)注意: 加密工具引用了之前修改过得文件
php_screw_plus.h
,说明加密工具和解密扩展是配对的,通过了CAKEY
产生关联。所以只能配对使用,每次修改CAKEY
之后都应该重新进行编译PHP
扩展和加密工具。
加密文件
下面还有最后一步,加密程序。
在扩展的tools
目录,执行./screw [路径]
,[路径]
可以是单个文件也可以是文件夹,然后就可以实现加密了。
加密完成后查看源码,可以发现除了开头的几个英文字符外,其余的都成了乱码。
但是打开网站,php
运行正常,如同没有加密一样。经过测试,解密速度大约为100M每秒,对php
自身的性能损失非常小,一般不到20毫秒。
screw plus
还有个功能,可阻止执行未经许可的php
文件,这样黑客就算上传了代码也然并卵。
同样在php_screw_plus.h
里修改,把STRICT_MODE
后面的值改为1
,然后make clean && make
重新编译并重启php
,然后打开之前加过密的网站,执行正常,但是我们随意上传个明文的php文件,结果是一片空白。
原因是未加密的php
文件头部不包含识别key
,扩展会返回空内容,就算黑客获取了key
并加入也没用,内容会被解密成乱码仍然无法执行。经过screw plus
的保护,即使网站整站被下载或被上传了恶意代码,也无法对网站造成损失
解密文件
执行./screw [path]
是加密 后面加-d参数则是解密 例如
./screw /home/web/ -d
使用中的注意事项
在laravel
框架加密代码并且解密扩展安装后发现本应该自动注册的命令行并没有注册成功。
通过修改app/Console/Kernel.php
中:
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->getClassCommands();
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
/**
* 容器内特殊处理,根据绝对路径进行类反射,参考load函数,对路径进行了修正
*/
protected function getClassCommands()
{
$paths = __DIR__ . '/Commands';
$paths = realpath($paths);
$paths = array_unique(Arr::wrap($paths));
$paths = array_filter($paths, function ($path) {
return is_dir($path);
});
if (empty($paths)) {
return;
}
$namespace = $this->app->getNamespace();
foreach (( new Finder )->in($paths)->files() as $command) {
$command = $namespace.str_replace(
['/', '.php'],
['\\', ''],
Str::after($command->getPathname(), realpath(app_path()) . DIRECTORY_SEPARATOR)
);
array_push($this->commands, $command);
}
}
vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php
中的 load
:
/**
* Register all of the commands in the given directory.
*
* @param array|string $paths
* @return void
*/
protected function load($paths)
{
$paths = array_unique(Arr::wrap($paths));
$paths = array_filter($paths, function ($path) {
return is_dir($path);
});
if (empty($paths)) {
return;
}
$namespace = $this->app->getNamespace();
foreach ((new Finder)->in($paths)->files() as $command) {
$command = $namespace.str_replace(
['/', '.php'],
['\\', ''],
Str::after($command->getPathname(), realpath(app_path()).DIRECTORY_SEPARATOR)
);
if (is_subclass_of($command, Command::class) &&
! (new ReflectionClass($command))->isAbstract()) {
Artisan::starting(function ($artisan) use ($command) {
$artisan->resolve($command);
});
}
}
}