安全工具 | Fscan 魔改二开 · 特征消除与功能扩展

🔧 安全工具 | Fscan 魔改二开 · 特征消除与功能扩展

📌 原fscan项目地址:https://github.com/shadow1ng/fscan

Fscan 是一款优秀的内网综合扫描工具,方便一键自动化、全方位漏扫扫描。在落地使用过程中,流量及文件不修改的情况下基本被检测查杀,针对这种情况,我们进行了一些基本的参数测试和特征去除,外加功能拓展。


📋 目录


一、环境准备

下载慢的可以配置国内加速镜像:

powershell 复制代码
$env:GO111MODULE = "on"
$env:GOPROXY = "https://goproxy.cn,direct"

二、直接编译测试

先不做任何修改,直接编译测一下各杀软的检测情况,作为改造前的基准对照。

原版编译

bash 复制代码
go build -ldflags="-s -w" -trimpath main.go

加上系统信息的详细版:

powershell 复制代码
$env:GOOS="windows"; $env:GOARCH="amd64"; go build -ldflags="-s -w" -trimpath main.go

无窗口模式(适合上线后台运行):

bash 复制代码
go build -ldflags="-s -w -H=windowsgui" -trimpath -o fscan_no_window.exe main.go

配合输出到文件:

bash 复制代码
.\fscan_no_window.exe -h 192.168.1.1/24 -o result.txt

⚠️ 测试结果:只改变编译模式,火绒直接杀了,说明单纯去符号表不够用。


三、特征字符串清除

原版二进制里包含大量明显特征,杀软直接按字符串匹配就能识别,需要逐一清除。

3.1 修改包名

第一步:改 go.mod

打开 go.mod,第一行是:

复制代码
module github.com/shadow1ng/fscan

改成随便一个名字,比如:

复制代码
module scanner/core

第二步:批量替换所有 import 路径

所有 .go 文件里的 github.com/shadow1ng/fscan 都要同步改,Windows 上用 PowerShell 批量替换:

powershell 复制代码
Get-ChildItem -Recurse -Filter "*.go" | ForEach-Object {
    (Get-Content $_.FullName) -replace 'github.com/shadow1ng/fscan', 'scanner/core' | Set-Content $_.FullName
}

第三步:改 Flag.go 里的版本号字符串

powershell 复制代码
grep -r "Fscan Version" . --include="*.go"

Fscan Version 改成别的,比如 Scanner Version,这也是特征字符串。

3.2 清除残留字符串

Common/Output.go

go 复制代码
// 把
Outputfile = filepath.Join(dir, "fscanapi.csv")
// 改成
Outputfile = filepath.Join(dir, "scannerapi.csv")

Plugins/MiniDump.go

go 复制代码
// 把
fmt.Sprintf("fscan-%d.dmp", pid)
// 改成
fmt.Sprintf("scanner-%d.dmp", pid)

3.3 修改 ASCII 艺术字

Common/Flag.go 里有启动时打印的 ASCII 艺术字,拼出来就是 "fscan",杀软能直接识别这个图案,直接清空:

go 复制代码
lines := []string{
    "  [*] Scanner Starting...",
}

3.4 重新编译

bash 复制代码
go build -o scanner.exe main.go

✅ 火绒过

✅ 360 静态过、杀毒、安全卫士、核晶体全过?????????

动态也能过????????

Defender 动态也能过????????

❌ 卡巴斯基静态被杀


四、编译层混淆(garble)

单纯清字符串对卡巴斯基这类引擎不够,它会分析代码结构。garble 能把函数名、变量名、字符串全部随机化,让杀软看不出来是什么工具。

前面一直用的是直接编译,这次换一下:

bash 复制代码
go build -ldflags="-s -w" -o scanner.exe main.go

❌ 结果:卡巴斯基依然杀,火绒也杀了,加 -ldflags 反而触发了启发式规则,效果更差。

4.1 安装 garble

bash 复制代码
go env -w GOPROXY=https://goproxy.cn,direct
go install mvdan.cc/garble@latest
go mod tidy

💡 garble 对 Go 版本有严格要求,目前支持 go1.25.x,太新或太旧都会报错。

4.2 基础混淆

bash 复制代码
garble -seed=random build -o scanner.exe main.go

✅ 火绒能过

❌ 卡巴斯基依旧被杀

4.3 试 UPX 加壳

下载地址:https://github.com/upx/upx/releases

bash 复制代码
upx --best scanner.exe -o scanner_upx.exe

❌ 卡巴斯基依旧被杀,然后 Defender 也杀了,加壳反而不行,过了段时间 360 也报了。加壳适得其反,不建议使用。

4.4 PE 资源伪装

使用 Restorator.exe 修改 PE 资源信息,添加图标、版本号、公司名等,伪装成正常软件:

⚠️ 没有效果。PE 资源伪装主要对付人眼识别,对杀软引擎的启发式检测基本没用。

4.5 garble 加上 -literals 字符串加密

bash 复制代码
garble -seed=random -literals build -o scanner.exe main.go

区别是:

  • 之前:只混淆函数名、变量名
  • 现在:额外把所有字符串加密,运行时动态解密

编译后体积会增大(约 90MB),但效果更好。

✅ 结果:卡巴斯基静态能过,Defender 被检测但只是禁止运行没有删除,应该是被 AMSI 检测了。

⚠️ 卡巴斯基动态运行一半就被杀了,检测到 POC 加载触发了,如果没扫到 POC 应该还是能稳一下的。


五、DLL 加载免杀

5.1 思路

把 fscan 编译成 DLL,再用一个 C 写的 loader 去加载它。杀软扫 loader 本身看不出是 fscan,从而绕过动态检测。

复制代码
scanner_loader.exe(C语言,干净)
      ↓ 加载
fscan.dll(实际功能)

5.2 修改 main.go

main.go 只保留一行:

go 复制代码
package main

5.3 新建 main-c.go,导出 Run 函数

go 复制代码
package main

import "C"
import (
    "fmt"
    "os"
    "scanner/core/Common"
    "scanner/core/Core"
)

//export Run
func Run() {
    Common.InitLogger()

    var Info Common.HostInfo
    Common.Flag(&Info)

    if err := Common.Parse(&Info); err != nil {
        os.Exit(1)
    }

    if err := Common.InitOutput(); err != nil {
        Common.LogError(fmt.Sprintf("初始化输出系统失败: %v", err))
        os.Exit(1)
    }
    defer Common.CloseOutput()

    Core.Scan(Info)
}

func main() {}

5.4 编译 DLL

powershell 复制代码
set CGO_ENABLED=1
set GOARCH=amd64
set GOOS=windows
go build -buildmode=c-shared -ldflags="-s -w" -o fscan.dll .

5.5 编写 C loader(main.c)

c 复制代码
#include <windows.h>
#include <stdio.h>

typedef void (*RunFunc)();

int main(int argc, char *argv[]) {
    HMODULE h = LoadLibraryA("fscan.dll");
    if (h == NULL) {
        printf("加载DLL失败: %d\n", GetLastError());
        return 1;
    }

    RunFunc run = (RunFunc)GetProcAddress(h, "Run");
    if (run == NULL) {
        printf("找不到Run函数: %d\n", GetLastError());
        return 1;
    }

    run();
    return 0;
}

5.6 编译 loader

bash 复制代码
x86_64-w64-mingw32-gcc -o scanner_loader.exe main.c -static

5.7 运行测试

scanner_loader.exefscan.dll 放在同一目录:

bash 复制代码
.\scanner_loader.exe -h 192.168.168.0/24

✅ 可以正常运行,扫描结果完整输出。
✅ 360 正常都能过

✅ Defender 都能过

❌ 卡巴斯基静态把 DLL 删了

💡 卡巴删的是 DLL,说明检测的是 DLL 内的 POC 行为特征,不是 loader。进一步绕过方向:内存加载 DLL(后续文章)。


六、功能扩展 · 添加新插件

fscan 2.0 的插件都在 Core/Registry.go 里统一注册,添加新插件分三步。

Zookeeper 未授权访问检测 为例(默认端口 2181):

💡 Zookeeper 是分布式协调服务,Kafka、Hadoop 等大数据组件都依赖它。默认没有认证机制,内网里很常见,是高频未授权访问漏洞。

6.1 安装依赖

bash 复制代码
go get github.com/samuel/go-zookeeper/zk

6.2 新建 Plugins/Zookeeper.go

go 复制代码
package Plugins

import (
    "fmt"
    "github.com/samuel/go-zookeeper/zk"
    "scanner/core/Common"
    "time"
)

func ZookeeperScan(info *Common.HostInfo) error {
    addr := fmt.Sprintf("%s:%v", info.Host, info.Ports)
    conn, _, err := zk.Connect([]string{addr}, time.Second*5)
    if err != nil {
        return err
    }
    defer conn.Close()
    Common.LogSuccess(fmt.Sprintf("未授权访问 Zookeeper %s:%v", info.Host, info.Ports))
    return nil
}

6.3 在 Core/Registry.go 里注册

init() 末尾加上:

go 复制代码
Common.RegisterPlugin("zookeeper", Common.ScanPlugin{
    Name:     "Zookeeper",
    Ports:    []int{2181},
    ScanFunc: Plugins.ZookeeperScan,
    Types:    []string{Common.PluginTypeService},
})

6.4 重新编译测试

bash 复制代码
go build -o scanner.exe main.go
.\scanner.exe -h 192.168.168.128 -p 2181

✅ 成功检测到 Zookeeper 未授权访问,插件列表里也能看到 zookeeper 已注册。


七、功能扩展 · 自定义 POC

fscan 支持在 pocs/ 目录下放 YAML 格式的 POC,扫到 Web 服务时自动加载检测,不需要重新编译

YAML POC 格式

yaml 复制代码
name: poc-yaml-CVE-2022-22947
rules:
  - method: POST
    path: /actuator/gateway/routes/hacktest
    headers:
      Content-Type: application/json
    body: |
      {
        "id": "hacktest",
        "filters": [{"name": "AddResponseHeader", "args": {"name": "Result", "value": "#{...}"}}],
        "uri": "http://example.com"
      }
    expression: response.status == 201
detail:
  author: xiaodisec
  links:
    - https://www.xiaodi8.com

逻辑很直观:发一个指定的请求,匹配返回结果,命中就判定漏洞存在。

使用方法

把 YAML 文件放到 pocs/ 目录下即可:

复制代码
scanner.exe
pocs/
  ├── CVE-2022-22947-spring-cloud-gateway.yml
  ├── CVE-2021-21972-vmcenter.yml
  └── ...

⚠️ pocs/ 目录要和 scanner.exe 放在同一目录才能读取,单独带走 exe 时记得把 pocs/ 一起打包。


八、效果汇总

各阶段免杀效果对比

阶段 操作 360 火绒 Defender 卡巴斯基
原版 无修改
第一轮 包名替换 + 字符串清除
第二轮 garble 基础混淆
UPX 加壳 加壳
第三轮 garble -literals 静态✅ 动态❌ 静态✅
DLL 加载 loader + dll dll被删

功能扩展汇总

功能 方式 说明
Zookeeper 未授权 Go 插件 检测 2181 端口未授权访问,需要重新打包
自定义 Web POC YAML pocs/ 目录下放 yml 文件即可,不需要

📝不是全部组合测试


系列下一篇:FScan 魔改二开 · 流量特征规避与指纹修改

相关推荐
SuperherRo7 小时前
JAVA攻防-Webshell免杀&JSP&JSPX脚本&URL类加载&远程分离&文件包含&工具特征消除
java·文件包含·webshell·url类加载·特征消除
jianghao202512 小时前
免安装的安全之选:黑科技工具箱的可靠性与便携性分析
安全工具·软件安全·便携应用
漏洞谷4 天前
白帽子为什么几乎都绕不开 httpx:一款 HTTP 资产探测工具的技术价值
web安全·漏洞挖掘·安全工具
恃宠而骄的佩奇2 个月前
蚁剑 php一句话木马简单免杀(编码)绕过360,火绒
开发语言·web安全·php·免杀·一句话木马·火绒安全
李白你好2 个月前
Webshell_Generate更新V1.2.6! | 各类webshell免杀,支持蚁剑、冰蝎、哥斯拉等
免杀
FAQEW3 个月前
若依微服务版(RuoYi-Cloud)本地启动全攻略
前端·后端·微服务·若依·二开
mooyuan天天3 个月前
万字讲解内网横向渗透vulnstack(四):红日靶场4实战全流程3-横向移动 zerologon法(CVE-2020-1472)
frp·内网渗透·横向移动·fscan·红日靶场·zerologon·cve-2020-1472
mooyuan天天3 个月前
万字讲解内网横向渗透vulnstack(一):红日靶场1实战全流程2-横向移动-永恒之蓝法(CVE-2017-0143)
内网渗透·fscan·永恒之蓝·红日靶场·横向渗透·cve-2017-0143
无名修道院3 个月前
渗透测试新手面试高频 50 题:原理 + 标准答案(2025)- 第三篇
网络安全·面试·职场和发展·渗透测试·内网渗透·免杀