
本文深入探讨了使用正则表达式检测混淆php函数调调用的复杂性,特别是那些通过字符串拼接(如`gzinflate(base64_decode(`)进行片段化的函数。文章阐述了简单正则表达式的局限性,提出了处理常见拼接模式的策略,并强调了为实现稳健检测而采用高级技术或外部工具的必要性。
在安全分析和恶意代码检测中,识别PHP代码中被混淆的函数调用是一个常见但复杂的任务。攻击者经常使用字符串拼接技术来隐藏恶意函数(如eval、gzinflate、base64_decode等),以规避静态分析工具和简单的正则表达式匹配。
例如,一个原本清晰的函数调用:
eval("gzinflate(base64_decode(\$data));");可能被混淆成以下形式:
eval("\$x=gzin"."flate(base"."64_de"."code(\$data));");在这种情况下,简单的正则表达式如gzinflate\(base64_decode\(将无法匹配,因为函数名被拆分成多个部分,并通过点号(.)运算符进行拼接。这种碎片化方式使得传统的模式匹配变得极其困难。
立即学习“PHP免费学习笔记(深入)”;
PHP提供了多种字符串拼接方式,其中最常见的是使用点号(.)运算符。此外,字符串还可以通过数组implode()函数、变量插值等方式动态构建。理解这些机制对于设计有效的检测策略至关重要。
例如,以下PHP代码片段展示了如何通过implode()函数将字符串片段组合起来,这正是攻击者常用来混淆代码的方式:
<?php $array = ["\$x=gzin", "flate(base", "64_de", "code(\$data))"]; $str = implode($array); // $str 现在包含: $x=gzinflate(base64_decode($data)) eval($str); // 最终执行混淆前的代码 ?>
这个例子虽然不是直接的正则表达式解决方案,但它揭示了混淆的本质:在代码执行前,碎片化的字符串会被重构成完整的函数名。这意味着,静态分析工具需要能够识别这些碎片以及它们之间的潜在连接方式。
面对字符串混淆,纯粹的正则表达式方法面临挑战。在寻求“更好的解决方案”时,我们需要在匹配的特异性(避免误报)和覆盖率(避免漏报)之间取得平衡。
对于目标函数名(如gzinflate和base64_decode),我们可以识别其常见的碎片化模式,并设计一个能够容忍这些碎片之间存在连接符的正则表达式。一个灵活的连接符模式可以匹配点号(.)运算符,以及可能存在的引号(")和空白字符(\s)。
我们可以定义一个通用连接符模式来匹配.、"."、" . "等形式: (?:"?\s*\.\s*"?)
现在,我们可以用这个连接符来构建匹配gzinflate和base64_decode的正则表达式:
匹配 gzinflate: 如果gzinflate可能被分成gzin和flate,则模式为: gzin(?:"?\s*\.\s*"?)flate
匹配 base64_decode: 如果base64_decode可能被分成base、64_de和code,则模式为: base(?:"?\s*\.\s*"?)64_de(?:"?\s*\.\s*"?)code
组合完整函数调用: 将这两个部分组合起来,匹配gzinflate(base64_decode(: (gzin(?:"?\s*\.\s*"?)flate)\((base(?:"?\s*\.\s*"?)64_de(?:"?\s*\.\s*"?)code)\(
示例代码:
注意事项: 这种策略的局限性在于,它仍然依赖于对碎片化模式的预知。如果攻击者使用不同的碎片化方式(例如,将gzinflate拆分成g、z、i、n、f、l、a、t、e九个部分),则上述模式将失效。
虽然提问者希望避免“在每个字母后都匹配"."”,但在某些极端情况下,为了最大化覆盖率,可能需要采用更细粒度的匹配方式。例如,匹配gzinflate可以写成:
g(?:"?\s*\.\s*"?)z(?:"?\s*\.\s*"?)i(?:"?\s*\.\s*"?)n(?:"?\s*\.\s*"?)f(?:"?\s*\.\s*"?)l(?:"?\s*\.\s*"?)a(?:"?\s*\.\s*"?)t(?:"?\s*\.\s*"?)e
这种模式理论上可以匹配任意字符级的碎片化,但它的缺点显而易见:
因此,这种方法通常被视为最后的手段,且需要仔细评估其带来的负面影响。
尽管正则表达式在模式匹配方面功能强大,但在面对高级PHP混淆时,它有其固有的局限性:
为了更有效地检测混淆的PHP代码,通常需要结合使用更高级的分析技术:
Yara规则: Yara是一种用于识别恶意软件家族的模式匹配工具。虽然Yara规则本身也使用字符串和正则表达式,但它允许通过逻辑运算符(and、or)组合多个规则和字符串,从而实现更复杂的检测逻辑。例如,可以创建多个规则来分别匹配gzinflate和base64_decode的碎片,然后用逻辑and将它们组合起来,并结合proximity(接近度)检查,确保这些碎片在代码中彼此靠近。
rule php_obfuscation_gzinflate_base64 {
strings:
$s_gzin = "gzin" nocase
$s_flate = "flate" nocase
$s_base = "base" nocase
$s_64_de = "64_de" nocase
$s_code = "code" nocase
$re_gzinflate = /gzin(?:"?\s*\.\s*"?)flate/ nocase
$re_base64_decode = /base(?:"?\s*\.\s*"?)64_de(?:"?\s*\.\s*"?)code/ nocase
condition:
// 尝试匹配完整的正则表达式
($re_gzinflate and $re_base64_decode) or
// 或者,匹配所有碎片,并确保它们在一定范围内出现
(all of ($s_gzin, $s_flate, $s_base, $s_64_de, $s_code) and
// 检查碎片之间的相对位置,例如,所有碎片都在文件的前500字节内
#s_gzin < 500 and #s_flate < 500 and #s_base < 500 and #s_64_de < 500 and #s_code < 500 and
// 更复杂的接近度检查可能需要外部脚本或更精细的Yara规则
// 例如,确保s_flate在s_
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号