基于C#实现一个简单的漏洞扫描器

 更新时间:2026年04月10日 09:16:51   作者:JQLvopkk  
本文介绍了使用C#开发一个简单的漏洞扫描器,具备端口扫描和基础Web漏洞检测功能,如SQL注入和XSS检测,文章提供了项目创建方法、完整代码、使用说明以及功能说明,还提到了局限性和改进方向,最后建议了功能拓展方向,需要的朋友可以参考下

下面是一个用 C# 开发简单漏洞扫描器的示例。它包含两个核心功能:

  1. 端口扫描:快速检测目标主机开放的 TCP 端口。
  2. 基础 Web 漏洞检测:对 HTTP/HTTPS 服务进行简单的 SQL 注入和 XSS 反射测试。

你可以在此基础上扩展服务识别、漏洞库匹配等高级功能。

1. 项目创建与依赖

建议使用 .NET 6/8 控制台应用。

dotnet new console -n SimpleVulnScanner cd SimpleVulnScanner

无需额外 NuGet 包,仅使用内置 System.Net.SocketsSystem.Net.Http

2. 完整代码

using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
namespace SimpleVulnScanner;
class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("=== 简单漏洞扫描器 (C#) ===");
        string target = GetTarget(args);
        int startPort = 1, endPort = 1024; // 默认扫描常见端口
        // 解析端口范围
        if (args.Length >= 2)
        {
            var portParts = args[1].Split('-');
            if (portParts.Length == 2 && int.TryParse(portParts[0], out int p1) && int.TryParse(portParts[1], out int p2))
            {
                startPort = p1;
                endPort = p2;
            }
            else if (int.TryParse(args[1], out int singlePort))
            {
                startPort = singlePort;
                endPort = singlePort;
            }
        }
        Console.WriteLine($"目标: {target}");
        Console.WriteLine($"端口范围: {startPort}-{endPort}");
        Console.WriteLine("开始端口扫描...\n");
        var openPorts = await PortScanner.ScanPortsAsync(target, startPort, endPort);
        Console.WriteLine("\n端口扫描完成。");
        if (openPorts.Count == 0)
        {
            Console.WriteLine("未发现开放端口。");
            return;
        }
        Console.WriteLine("开放端口列表:");
        foreach (var port in openPorts)
        {
            string service = PortScanner.GuessService(port);
            Console.WriteLine($"  {port}/tcp  ({service})");
        }
        // 对常见 Web 端口进行漏洞检测
        var webPorts = openPorts.Where(p => p == 80 || p == 443 || p == 8080 || p == 8443).ToList();
        if (webPorts.Any())
        {
            Console.WriteLine("\n开始 Web 漏洞检测...");
            foreach (var port in webPorts)
            {
                string scheme = port == 443 || port == 8443 ? "https" : "http";
                string baseUrl = $"{scheme}://{target}:{port}";
                await WebVulnScanner.ScanAsync(baseUrl);
            }
        }
        Console.WriteLine("\n扫描结束。按任意键退出...");
        Console.ReadKey();
    }
    static string GetTarget(string[] args)
    {
        if (args.Length > 0 && !string.IsNullOrEmpty(args[0]))
            return args[0];
        Console.Write("请输入目标 IP 或域名: ");
        return Console.ReadLine()?.Trim() ?? "127.0.0.1";
    }
}
// ---------- 端口扫描模块 ----------
public static class PortScanner
{
    private const int TimeoutMs = 1000;
    private const int MaxConcurrency = 100;
    public static async Task<List<int>> ScanPortsAsync(string host, int startPort, int endPort)
    {
        var openPorts = new List<int>();
        var semaphore = new SemaphoreSlim(MaxConcurrency);
        var tasks = new List<Task>();
        for (int port = startPort; port <= endPort; port++)
        {
            await semaphore.WaitAsync();
            int currentPort = port;
            tasks.Add(Task.Run(async () =>
            {
                try
                {
                    if (await IsPortOpenAsync(host, currentPort))
                    {
                        lock (openPorts)
                        {
                            openPorts.Add(currentPort);
                            Console.WriteLine($"[+] 开放: {currentPort}/tcp");
                        }
                    }
                }
                finally
                {
                    semaphore.Release();
                }
            }));
        }
        await Task.WhenAll(tasks);
        openPorts.Sort();
        return openPorts;
    }
    private static async Task<bool> IsPortOpenAsync(string host, int port)
    {
        try
        {
            using var client = new TcpClient();
            var connectTask = client.ConnectAsync(host, port);
            var timeoutTask = Task.Delay(TimeoutMs);
            var completedTask = await Task.WhenAny(connectTask, timeoutTask);
            if (completedTask == timeoutTask)
                return false;
            return client.Connected;
        }
        catch
        {
            return false;
        }
    }
    public static string GuessService(int port)
    {
        return port switch
        {
            21 => "FTP",
            22 => "SSH",
            23 => "Telnet",
            25 => "SMTP",
            80 => "HTTP",
            110 => "POP3",
            143 => "IMAP",
            443 => "HTTPS",
            3306 => "MySQL",
            3389 => "RDP",
            5432 => "PostgreSQL",
            8080 => "HTTP-Proxy",
            _ => "未知"
        };
    }
}
// ---------- Web 漏洞检测模块 ----------
public static class WebVulnScanner
{
    private static readonly HttpClient _httpClient;
    static WebVulnScanner()
    {
        var handler = new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true // 忽略证书错误
        };
        _httpClient = new HttpClient(handler);
        _httpClient.Timeout = TimeSpan.FromSeconds(10);
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "SimpleVulnScanner/1.0");
    }
    public static async Task ScanAsync(string baseUrl)
    {
        Console.WriteLine($"\n[*] 扫描 Web 服务: {baseUrl}");
        // 1. 检测 SQL 注入(基于错误回显)
        await TestSqlInjectionAsync(baseUrl);
        // 2. 检测反射型 XSS
        await TestReflectedXssAsync(baseUrl);
    }
    private static async Task TestSqlInjectionAsync(string baseUrl)
    {
        string[] sqlPayloads = { "'", "\"", "' OR '1'='1", "\" OR \"1\"=\"1", "' OR 1=1--", "\" OR 1=1--" };
        var errorPatterns = new[]
        {
            "SQL syntax", "mysql_fetch", "ORA-", "PostgreSQL", "SQLite", "Microsoft OLE DB",
            "Unclosed quotation mark", "You have an error in your SQL syntax"
        };
        foreach (var payload in sqlPayloads)
        {
            string testUrl = $"{baseUrl}/?id={Uri.EscapeDataString(payload)}";
            try
            {
                var response = await _httpClient.GetAsync(testUrl);
                string content = await response.Content.ReadAsStringAsync();
                foreach (var pattern in errorPatterns)
                {
                    if (content.Contains(pattern, StringComparison.OrdinalIgnoreCase))
                    {
                        Console.WriteLine($"  [!] 可能存在 SQL 注入 (错误回显) - Payload: {payload}");
                        return; // 仅报告一次
                    }
                }
            }
            catch (Exception ex)
            {
                // 忽略网络错误
            }
        }
    }
    private static async Task TestReflectedXssAsync(string baseUrl)
    {
        string xssPayload = "<script>alert('XSS')</script>";
        string testUrl = $"{baseUrl}/?q={Uri.EscapeDataString(xssPayload)}";
        try
        {
            var response = await _httpClient.GetAsync(testUrl);
            string content = await response.Content.ReadAsStringAsync();
            // 检查 payload 是否原样反射在响应中
            if (content.Contains(xssPayload))
            {
                Console.WriteLine($"  [!] 可能存在反射型 XSS - Payload 已回显");
            }
        }
        catch
        {
            // 忽略
        }
    }
}

3. 使用说明

命令行参数

dotnet run <目标IP/域名> [端口范围]

示例:

# 扫描 127.0.0.1 的 1-1024 端口
dotnet run 127.0.0.1
# 扫描 192.168.1.1 的 80-100 端口
dotnet run 192.168.1.1 80-100
# 扫描单个端口 443
dotnet run example.com 443

若未提供参数,程序会交互式询问目标。

运行截图示意

=== 简单漏洞扫描器 (C#) ===
目标: 192.168.1.1
端口范围: 1-1024
开始端口扫描...
[+] 开放: 80/tcp
[+] 开放: 443/tcp
[+] 开放: 22/tcp
端口扫描完成。
开放端口列表:
  22/tcp  (SSH)
  80/tcp  (HTTP)
  443/tcp  (HTTPS)
开始 Web 漏洞检测...
[*] 扫描 Web 服务: http://192.168.1.1:80
  [!] 可能存在 SQL 注入 (错误回显) - Payload: '
  [!] 可能存在反射型 XSS - Payload 已回显
[*] 扫描 Web 服务: https://192.168.1.1:443
扫描结束。按任意键退出...

4. 功能说明与局限性

功能实现方式说明
端口扫描TCP Connect 异步扫描超时 1 秒,并发 100,速度快且准确
服务猜测静态映射表根据常见端口号推测服务名称
SQL 注入检测发送 ' 等 payload,匹配错误关键词仅检测错误回显型,不适用于盲注
XSS 检测发送 <script>alert('XSS')</script> 并检查回显仅检测反射型,不适用于 DOM 型

局限性与改进方向

  • 端口扫描:容易被防火墙拦截,可改用 SYN 半开扫描(需更高权限)。
  • Web 漏洞检测:非常基础,实际环境中应集成更全面的 payload 和智能分析(如基于 DOM 的变化)。
  • 服务识别:目前仅靠端口猜测,可增加 Banner 抓取。
  • 多线程安全:已使用 SemaphoreSlim 控制并发,避免资源耗尽。

5. 扩展建议

如果你想增强这个扫描器,可以考虑以下方向:

  1. Banner 抓取:在端口开放后发送特定协议探测包(如 HTTP GET、SMTP EHLO),获取服务版本信息。
  2. 漏洞库匹配:将识别到的服务版本与 CVE 数据库对比。
  3. 爬虫与表单扫描:对发现的 Web 服务进行爬取,自动填充表单进行 SQLi / XSS 测试。
  4. 报告生成:将扫描结果输出为 JSON 或 HTML 报告。
  5. 插件化架构:使用 MEF 或反射加载自定义检测模块。

以上就是基于C#实现一个简单的漏洞扫描器的详细内容,更多关于C#漏洞扫描器的资料请关注脚本之家其它相关文章!

相关文章

  • C#如何自定义multipart/form-data的解析器

    C#如何自定义multipart/form-data的解析器

    这篇文章主要介绍了C#如何自定义multipart/form-data的解析器,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • C# 定时器保活机制引起的内存泄露问题解决

    C# 定时器保活机制引起的内存泄露问题解决

    这篇文章主要介绍了C# 定时器保活机制引起的内存泄露问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • C#类的访问修饰符用法分析

    C#类的访问修饰符用法分析

    这篇文章主要介绍了C#类的访问修饰符用法,较为详细的分析了C#类的访问修饰符概念与用法,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-10-10
  • C#中四种定时器的用法详解

    C#中四种定时器的用法详解

    日常项目开发中,很多时候都需要用到定时器来处理一些问题,那么c#中各种定时器应该怎么用呢?下面来简单介绍下C#中4种定时器的使用方法说明,感兴趣的朋友可以参考下
    2024-04-04
  • C#去掉字符串中所有匹配的字符String.Replace方法

    C#去掉字符串中所有匹配的字符String.Replace方法

    在C#中,如果你想要去掉字符串中所有匹配的字符,你可以使用String.Replace方法,本文主要介绍了C#去掉字符串中所有匹配的字符String.Replace方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • C#控制IE进程关闭和缓存清理的实现代码

    C#控制IE进程关闭和缓存清理的实现代码

    这篇文章主要介绍了C#控制IE进程关闭和缓存清理的实现代码,需要的朋友可以参考下
    2014-04-04
  • C#基础知识之Partial的使用

    C#基础知识之Partial的使用

    这篇文章主要介绍了C#基础知识之Partial的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 在C#项目中调用C++编写的动态库的三种方式

    在C#项目中调用C++编写的动态库的三种方式

    这篇文章给大家介绍了三种方式详解如何在C#项目中调用C++编写的动态库,文中通过代码示例给大家介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-01-01
  • c# 实现打印机状态查询与阻塞打印

    c# 实现打印机状态查询与阻塞打印

    这篇文章主要介绍了c# 引用System.Management来实现对打印机状态的查询,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-05-05
  • C#的this关键字的2种用法

    C#的this关键字的2种用法

    这篇文章主要给大家分享的是C#的this关键字的2种用法,在使用C#的过程中,发现this关键是比较少用的,但是在下面这二个场合下是必须要使用的,不使用它是解决不了问题。下面我们就来看看文章的具体内容吧
    2021-10-10

最新评论