看到全是十六进制的PHP代码文件?

前几天在网上看到一份代码,打开来看,里面都是类似下面的十六进制字符串。一脸懵逼,啥情况,我万能的sublime text 打开居然是十六进制文件,而且文件居然还能运行?

3c3f 7068 700d 0a6e 616d 6573 7061 6365

2061 7070 3b24 5f53 4552 5645 525b 5048

505f 454f 4c5d 203d 2065 7870 6c6f 6465

使用万能的记事本打开一看里面一段可见的部分引起注意

$_SERVER[PHP_EOL] = explode(
",", 
gzinflate('?      ?N?I-.袸+退-N K扮?   ',10,-8)
);

于是仔细研究了一下。

常见的几种PHP代码加密方式

1.opecode 方式

将PHP代码直接编译为opcode代码,有点类似于java种的class文件。采用这种方式避免源码暴露出来。因为Zend引擎最终执行的是opcode,只要保证能解密出opcode就能保证程序正常运行,只要简单的将opcode进行简单的序列化或者像Zend Guard那样进行混淆,在运行之前将opcode还原,那么源代码的信息就不存在了,这样我们就能保证源代码的安全, 而不至于泄露。

通过扩展的方式对加密文件进行解密

因为php程序运行前都会执行扩展的方法,所以通过扩展的方式对php源码进行保护可以有很多形式。

  • 源码许可验证。通过扩展在程序执行前验证代码的licence可以避免盗版使用的情况。
  • 通过hash验证,验证源码是否被修改
  • 对核心代码进行加密,甚至放在扩展中运行,避免被破解。

直接对PHP代码进行混淆,加到源码阅读难度

这种方式不是真正意义上的加密,只是对代码进行混淆。将PHP代码中的变量,方法名称等换成毫无意义的表示符号。代码混淆有多种处理方式。

  • 将代码文件作为字符串进行base64编码,然后使用evel的方式在执行的过程中对文件进行base64解码运行。这种方式对原来的代码内部变化比较小。只是换了一种现实方式而已。
  • 通过正则方式替换变量符号,函数名称等。这种方式替换会有很大的不确定性。因为已经在实质上修改了原有的代码,容易造成变量冲突,类属性不存在等错误。特别对于通过魔术方式等设置的类属性,或者通过依赖注入方式,回调方式创建的对象,这种替换会使得代码无法运行。
  • 创建一个全局数组作为替换码表。将所有字符串进行替换。这种方式不改变类属性的名称,方法的名称等。只是将所有的变量名称,方法名称替换成码表种的值。将码表进行加密存,在程序入口进行解密,保证后续代码能正常运行。这种方式只要替换正确都能保证代码可运行。

目前网上的代码基本上都是使用混淆的方式。因为这些代码都不能要求用户使用特定的扩展,同时为了保证代码客运行,基本上都是在一些核心文件才会使用混淆,对代码进行混淆。

对于文章开始混淆前代码

<?phpnamespace app;class Test{	public $msg;	public function setMsg($msg){		$this->msg = $msg;
}	public function getMsg(){
$hex = 'haha';
$tys = '8';		return $this->msg;
}
}
$t = new Test();
$t->setMsg('hahahahah');
var_dump($t->getMsg());

混淆后的代码

<?phpnamespace app;
$_SERVER[PHP_EOL] = explode(
",", 
gzdecode(?      薍)?? Wc?	   ));
 class Test { 
 public $msg; 
 public function test(${$_SERVER[PHP_EOL][0]}) { $this->msg = ${$_SERVER[PHP_EOL][0]}; } public function {$_SErVer[php_eol][2]}() { goto {$_SERVER[PHP_EOL][55]}; {$_SERVER[PHP_EOL][57]}: return $this->msg; goto {$_SERVER[PHP_EOL][58]}; {$_SERVER[PHP_EOL][56]}: ${$_SERVER[PHP_EOL][17]} = "\70"; goto {$_SERVER[PHP_EOL][57]}; {$_SERVER[PHP_EOL][55]}: ${$_SERVER[PHP_EOL][16]} = "\150\x61\x68\141"; goto {$_SERVER[PHP_EOL][56]}; {$_SERVER[PHP_EOL][58]}: } } ${$_SERVER[PHP_EOL][18]} = new Test(); ${$_SERVER[PHP_EOL][18]}->{$_SERVER[PHP_EOL][1]}("\150\141\x68\x61\x68\141\150\x61\x68"); var_dump(${$_SERVER[PHP_EOL][18]}->{$_SERVER[PHP_EOL][2]}());

编辑器打开是十六进制,其实是一个障眼法。主要是目前编辑器在检测到文件前有特殊字符就会当做十六进制文件进行显示!!因此当我们把码表转换成字符串,进行gz压缩之后肯定会有特殊字符,然后把它放在文件开始的地方,编辑器打开就是十六进制显示方式。

原文发布于微信公众号 - 写PHP的老王(laowang_php)

原文发表时间:2018-07-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券