介绍
文件认证模板是 Crane · 第二代加密引擎为魔方+用户提供的功能。
常见的“文件认证”包括:
- 检测服务器 IP 是否正确
- 检测服务器主机名是否正确
- 检测网站的域名是否正确
- 检测当前时间是否在某个范围之内
- 使用其它方法检测文件是否允许运行
与传统的实现方法不同,使用文件认证模板的步骤为:
- 编写不含任何认证代码的源文件
- 编写文件认证模板
- 将两个文件上传魔方加密进行加密,加密时两个文件将会自动融合
通过使用文件认证模板功能,魔方加密会把认证代码 随机数量、随机位置 嵌入到源文件中。两个文件融合的过程类似于“埋地雷”,认证代码的数量、位置都是随机的、不可预测的。这就意味着,攻击者若想破解文件,必须要将文件中埋设的所有认证代码全部破坏,否则只要遗留一处,认证代码依然有效。
编写方法
文件认证模板是一个合法的 PHP 文件。
以下是一个文件认证模板的例子:
<?php
#inline-invoke
if(0) {
// 初始化检测
}
#inline-invoke
if(0) {
// 检测代码 1
if($_SERVER['HTTP_HOST'] != '127.0.0.1') return;
}
#inline-invoke
if(0) {
// 检测代码 2
if(getenv('HTTP_HOST') != '127.0.0.1') return;
}
#inline-invoke
if(0) {
// 检测代码 3
if(empty($_SERVER['HTTP_HOST'])) return;
}
#inline-invoke
if(0) {
// 检测代码 4
if(getenv('HTTP_HOST') != $_SERVER['HTTP_HOST']) return;
}
#inline-return
if(0) {
// 错误提示 1
exit('<i>文件 ', basename(__FILE__), ' 必须运行在 127.0.0.1 的域名下</i>');
}
#inline-return
if(0) {
// 错误提示 2
exit('<b>文件 ', basename(__FILE__), ' 必须运行在 127.0.0.1 的域名下</b>');
}
可以看出,文件认证模板中分为多个块,块的结构为:
#inline-???
if(0) {
// 具体的实现代码
}
块以 #inline-???
开头,开头标识了下面的 if(0) { ... }
内部的代码的用途。
认证块
#inline-invoke
认证块中的代码应当是实际的认证代码。如果有多种实现认证的方法,可以编写多个认证块,每个块中实现一种检测。
认证失败请调用
return
,魔方加密会随机选择一个错误提示块的内容替换return
语句。错误提示块
#inline-return
错误提示块中的代码用以提示用户文件不可运行,或者实现其它记录操作。
请注意,无论错误提示块中的代码是否调用了
exit
,块中的代码执行完毕后 PHP 脚本都会终止。
文件认证模板应该含有至少 1 个认证块和 1 个错误提示块。
加密时,融合的过程如下:
- 编译上传的文件认证模板,提取所有认证块和错误提示块
- 遍历处理所有的认证块,将认证块代码中的
return
语句使用一个随机的错误提示块代码进行替换 - 编译需要加密的源文件,将认证块代码、错误提示块代码融合后得到的 Opcode 按照一定的概率随机数量、随机位置插入源文件编译得到的 Opcode 中
- 根据合并后的 Opcode 生成最后的加密文件
效率改进
认证块会被随机插入到文件的任何位置,尤其当被插入到循环内部时,代码执行效率可能会严重下降。
使用编译杂注 #inline-ignore
可以提示编译器,不要在某个语句块中插入认证块。
<?php
#inline-ignore
for($i = 0; $i < 10; $i ++) {
// do something
}
在以上的待加密示例代码中,for
循环前使用编译杂注 #inline-ignore
,使得在 for
循环内部不会被插入任何认证块。
更多提示
- 第一个认证块仅会插入文件和函数的开头,并不会随机插入其它位置,因此,初始化认证相关代码应当放置在第一个认证块中
- 切勿在编写过于庞大的代码,这会导致加密文件体积巨大,且执行效率降低
- 不要轻易相信
$_SERVER
中的数据,因为这个数组可以被篡改 - 检测时间时注意考虑时差问题