前言:红队打点中的“见光死”痛点 在日常的内网渗透或红队演练中,端口扫描和指纹识别是必不可少的一环。然而,主流优秀的开源扫描器由于其极高的知名度,其二进制文件早已被各大安全厂商(如卡巴斯基、360、Windows Defender)加入了静态特征黑名单。 很多时候,扫描器刚刚上传到目标机器,还没来得及敲击回车,就被杀毒软件无情斩杀。为了解决这个痛点,我对某知名 Go 语言开源高并发扫描器进行了深度的免杀改造

一、 静态特征抹除:为什么用 AST 自动化加密?

1. 遇到的问题 杀毒软件最基础的查杀手段是“静态特征码匹配”。对于资产扫描器来说,代码里写满了成百上千种协议的探测包(Probe)响应指纹(Fingerprint)。比如识别某框架时特有的 HTTP 请求头、SMB 的握手协议特征等。只要杀软提取到这些硬编码的指纹特征,就会直接报警。

2. 传统方案的局限 以前常见的做法是给 .exe 文件“加壳”(如 UPX),但现在的杀软脱壳技术非常成熟,加壳文件往往会被直接标记为高危。

3. 我的改造方案:AST 自动化加密 与其加壳,不如直接在代码里把所有的探测包和指纹密文化。但我不可能手动去改几万行代码和几千条配置。因此,我引入了 AST(抽象语法树) 技术。

简单科普:AST 可以理解为一种“能让代码自动分析和修改代码”的底层语法工具。

我写了一个自动化脚本,利用 AST 遍历了扫描器的所有源代码,找到了里面所有的指纹常量和明文字符串:

  • 编译前:脚本将所有的明文字符串提取出来,使用AES和Base64算法进行了高强度加密。
  • 运行时:脚本自动在这些字符串原本的位置,插入了一个Decrypt解密函数。

代码对比非常直观:

改造前,代码是明文的,包含了明显的指纹识别特征码,杀软一查一个准:

// 原始代码,包含了明显的资产指纹特征

func IdentifyFramework() {

// 明显的 HTTP 探测请求头

probeReq := "GET /manager/html HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"

// 明显的框架响应特征

fingerprint := "Server: Apache-Coyote/1.1"

fmt.Println("[+] Detected Tomcat Server")

}

被 AST 脚本自动化改造后,代码变成了这样:

// 改造后的代码,源码中不再有任何静态特征

func IdentifyFramework() {

// 探测包和指纹特征只在运行时才会被动态解密出来,在内存中一闪而过

probeReq := pkg.Decrypt("yX8Hkjh/9sdHkasd9+9ad8hB1Vw...")

fingerprint := pkg.Decrypt("aG8PzQ1T/B7xKlOq...")

fmt.Println(pkg.Decrypt("oP1sdHka2Mm9..."))

}

通过这种方式,编译出来的最终程序里,所有敏感的协议探测数据和指纹库都变成了毫无逻辑的乱码。杀软的静态特征库直接失效。

二、 动态行为规避:Anti-Sandbox(反沙箱) 机制

1. 遇到的问题 现在的杀软很聪明,即使它找不到静态特征,它也会把你的程序放进一个名为“沙箱(Sandbox)”的虚拟环境中试运行一下。如果沙箱观察到程序在发起恶意扫描,同样会将其查杀。

2. 我的改造方案:环境检测与资源消耗 杀软的虚拟沙箱虽然能模拟真实的电脑,但为了节省服务器资源,沙箱的配置通常很低,且对每个程序的分析时间有严格的限制(比如只运行3秒钟看结果)。 针对这一点,我在程序的启动入口(init 函数)加入了以下两层防御代码:

package pkg

import (

"os"

"runtime"

)

func init() {

// 防御层1:检测 CPU 核心数

// 如果发现当前机器的核心数小于2,极大概率是遇到了简陋的沙箱环境,程序直接退出,不给沙箱分析的机会。

if runtime.NumCPU() < 2 {

os.Exit(0)

}

// 防御层2:算力拖延

// 我们强制程序在启动前去计算 20万以内的所有素数。

// 这对于正常电脑来说只需要极短的时间,但对于资源受限的沙箱,会导致 CPU 满载并大幅拖延启动时间,往往能直接拖到沙箱分析超时。

count := 0

for i := 2; i < 200000; i++ {

// ... (素数计算算法)

}

}

有了这段代码,扫描器在被杀软检测时就会“装死”,成功躲过动态分析。

三、 实战化考量:为什么这个免杀版本高达 16MB?

很多开源扫描器需要配合外部的 .json 或 .yaml 配置文件才能运行。但在实战中,程序频繁读取外部文件很容易触发主机防御系统(HIPS)的拦截。

为了做到“真正的无痕落地”,我使用了 Go 语言内置的 go generate 机制。在编译阶段,我将几千条漏洞验证规则、端口识别指纹,全部转化为字节流硬编码到了可执行文件中

这直接导致最终生成的 .exe 文件体积达到了 16MB。 体积变大并不是缺点,而是纯静态打包的必然结果。这 16MB 里包含了加密后的海量武器库,在实战时你只需要传这一个文件就能直接开扫,彻底摆脱了对外部配置文件的依赖,极大地提升了隐蔽性。

实战演示 我们在开启了卡巴斯基全功能的 Windows 环境下进行测试:

⚠️ 郑重声明: 本文介绍的技术与相关工具仅供合法的授权网络安全测试、红蓝对抗演练以及安全技术研究使用。切勿用于任何非法网络攻击,否则后果自负。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐