实例介绍
using System;
using System.Collections.Concurrent;using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using VulnScanner.Core;
using VulnScanner.Models;
using VulnScanner.Reporting;
namespace VulnScanner.UI;
public partial class MainForm : Form
{
readonly string? _demoBaseUrl;
ScanEngine? _engine;
readonly List<Finding> _findings = new();
readonly object _lock = new();
Severity? _filter = null;
// 批量刷新队列——扫描线程只塞数据,UI定时器批量取
readonly ConcurrentQueue<Finding> _pendingFindings = new();
readonly ConcurrentQueue<string> _pendingLogs = new();
readonly System.Windows.Forms.Timer _uiTimer = new();
int _progressTotal, _progressCompleted, _progressFindings;
bool _scanRunning;
public MainForm() : this(null) { }
public MainForm(string? demoBaseUrl)
{
_demoBaseUrl = demoBaseUrl;
// 双缓冲防闪烁
DoubleBuffered = true;
InitializeComponent();
// DataGridView 双缓冲
typeof(DataGridView).InvokeMember("DoubleBuffered",
System.Reflection.BindingFlags.SetProperty | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,
null, resultGrid, new object[] { true });
txtUsers.Text = string.Join(",", Wordlists.DefaultUsers);
txtPasswords.Text = string.Join(",", Wordlists.DefaultPasswords);
// 默认空项填充专业值
txtUserAgent.Text = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
txtProxy.Text = "";
txtUsersFile.Text = "";
txtPasswordsFile.Text = "";
txtExtraFields.Text = "remember_me=on";
txtDirList.Text = "";
txtServicePorts.Text = "21,22,23,111,135,139,445,512,513,514,873,1099,1433,1521,2049,2181,2375,2376,3306,3389,4848,5000,5432,5601,5900,5984,6379,7001,7002,8000,8009,8080,8081,8161,8443,8500,8686,8848,8888,9000,9001,9043,9090,9200,9300,10000,11211,15672,27017,27018,27019,50070";
txtExtraPorts.Text = "8080,8443,9090,8000,8888,7001,5000,3000,9200,5601,15672,8500,2375,10250";
txtPostTargets.Text = "http://{host}/login|username,password\nhttp://{host}/api/login|user,pass";
// 表单字段默认值(多字段自动尝试)
txtUserField.Text = "username,user,login,email,account,name,j_username,userid";
txtPassField.Text = "password,pass,passwd,pwd,j_password,userpass";
chkModules.Items.AddRange(new object[] {
"SQL注入", "弱口令:HTTP Basic", "弱口令:表单登录",
"弱口令:FTP/MySQL/Redis", "目录/敏感文件", "端口扫描",
"反射型XSS", "信息收集", "敏感信息检测",
"命令注入", "路径遍历", "SSTI模板注入",
"安全响应头", "CORS跨域", "SMB共享目录", "未授权访问/敏感端点", "危险HTTP方法",
"SSRF服务端请求伪造", "XXE外部实体注入", "开放重定向", "JWT安全检测",
"CRLF注入", "文件上传", "反序列化", "IDOR越权", "CSRF跨站请求",
"HTTP请求走私", "GraphQL检测", "WebDAV检测", "子域接管检测", "TLS/SSL检测", "WAF识别"
});
for (int i = 0; i < chkModules.Items.Count; i ) chkModules.SetItemChecked(i, true);
btnFilterAll.Click = (_, _) => SetFilter(null);
btnFilterCritical.Click = (_, _) => SetFilter(Severity.Critical);
btnFilterHigh.Click = (_, _) => SetFilter(Severity.High);
btnFilterMedium.Click = (_, _) => SetFilter(Severity.Medium);
btnFilterLow.Click = (_, _) => SetFilter(Severity.Low);
btnFilterInfo.Click = (_, _) => SetFilter(Severity.Info);
resultGrid.CellDoubleClick = ResultGrid_DoubleClick;
// UI批量刷新定时器:每200ms处理积压事件
_uiTimer.Interval = 200;
_uiTimer.Tick = UiTimer_Tick;
_uiTimer.Start();
if (!string.IsNullOrEmpty(demoBaseUrl))
{
Shown = async (_, _) => await RunDemo(demoBaseUrl);
}
FormClosing = MainForm_FormClosing;
// 注册页初始化
var mc = Licensing.GetMachineCode();
txtMachineCode.Text = mc;
// 加载微信二维码
try
{
var qrPath = Path.Combine(AppContext.BaseDirectory, "wechat_qr.jpg");
if (File.Exists(qrPath))
picQr.Image = Image.FromFile(qrPath);
}
catch { }
btnRegister.Click = (_, _) =>
{
if (Licensing.SaveRegistration(txtRegCode.Text))
{
lblRegStatus.Text = "注册成功!感谢授权。";
lblRegStatus.ForeColor = Color.LimeGreen;
btnStart.Enabled = true;
MessageBox.Show("注册成功!", "提示");
}
else
{
lblRegStatus.Text = "注册码错误,请核对后重试。";
lblRegStatus.ForeColor = Color.OrangeRed;
MessageBox.Show("注册码错误", "错误");
}
};
bool licensed = Licensing.IsRegistered();
if (licensed)
{
lblRegStatus.Text = "已注册(正式授权)";
lblRegStatus.ForeColor = Color.LimeGreen;
btnStart.Enabled = true;
}
else
{
var days = Licensing.RemainingTrialDays();
if (days > 0)
{
lblRegStatus.Text = $"试用版:剩余 {days} 天,请及时注册。";
lblRegStatus.ForeColor = Color.Orange;
btnStart.Enabled = true;
}
else
{
lblRegStatus.Text = "试用期已结束,请注册后使用。";
lblRegStatus.ForeColor = Color.Red;
btnStart.Enabled = false;
MessageBox.Show("试用3天已结束,请注册后使用。\r\n\r\n联系人:小马 电话/微信:15812096485",
"试用期结束", MessageBoxButtons.OK, MessageBoxIcon.Warning);
tabs.SelectedTab = pageRegister;
}
}
}
void MainForm_FormClosing(object? sender, FormClosingEventArgs e)
{
try
{
// 扫描中不允许退出
if (IsScanning)
{
MessageBox.Show("扫描正在进行中,请先点击「停止」按钮,等待所有任务完成后再退出。",
"无法退出", MessageBoxButtons.OK, MessageBoxIcon.Warning);
e.Cancel = true;
return;
}
_uiTimer.Stop();
_engine?.Stop();
_engine?.Dispose();
}
catch { }
}
void BtnExit_Click(object? sender, EventArgs e) => Close();
bool IsScanning => btnStart.Enabled == false && btnStop.Enabled == true;
void UiTimer_Tick(object? sender, EventArgs e)
{
try
{
// 批量处理新发现
bool findingsChanged = false;
while (_pendingFindings.TryDequeue(out var f))
{
lock (_lock) _findings.Add(f);
if (!_filter.HasValue || f.Severity == _filter.Value)
AddRow(f);
findingsChanged = true;
}
if (findingsChanged) UpdateStatus();
// 批量处理日志
if (!_pendingLogs.IsEmpty)
{
var sb = new System.Text.StringBuilder();
while (_pendingLogs.TryDequeue(out var msg))
sb.Append('[').Append(DateTime.Now.ToString("HH:mm:ss")).Append("] ").Append(msg).Append("\r\n");
logBox.AppendText(sb.ToString());
}
// 进度
if (_progressTotal > 0)
{
int pct = (int)Math.Min(100, (double)_progressCompleted / _progressTotal * 100);
if (progressBar.Value != pct) progressBar.Value = pct;
lblProgress.Text = $" {_progressCompleted}/{_progressTotal} 发现:{_progressFindings}";
}
}
catch { }
}
void SetFilter(Severity? sev)
{
try { _filter = sev; RefreshGrid(); } catch { }
}
void RefreshGrid()
{
lock (_lock)
{
resultGrid.SuspendLayout();
resultGrid.Rows.Clear();
foreach (var f in _findings)
{
if (_filter.HasValue && f.Severity != _filter.Value) continue;
AddRow(f);
}
resultGrid.ResumeLayout();
}
}
void AddRow(Finding f)
{
try
{
var idx = resultGrid.Rows.Add(f.Time.ToString("HH:mm:ss"), f.Severity.Display(), f.Module, f.Name, f.Url, f.Detail);
var sevColor = f.Severity switch
{
Severity.Critical => Color.FromArgb(255, 105, 105),
Severity.High => Color.FromArgb(255, 183, 77),
Severity.Medium => Color.FromArgb(255, 235, 120),
Severity.Low => Color.FromArgb(130, 200, 255),
_ => Color.FromArgb(150, 170, 200),
};
resultGrid.Rows[idx].Cells[1].Style.ForeColor = sevColor;
resultGrid.Rows[idx].Cells[1].Style.Font = new Font("Microsoft YaHei UI", 10F, FontStyle.Bold);
resultGrid.Rows[idx].Tag = f;
}
catch { }
}
void UpdateStatus()
{
int cC = 0, cH = 0, cM = 0, cL = 0, cI = 0;
lock (_lock)
{
foreach (var f in _findings)
{
switch (f.Severity)
{
case Severity.Critical: cC ; break;
case Severity.High: cH ; break;
case Severity.Medium: cM ; break;
case Severity.Low: cL ; break;
default: cI ; break;
}
}
}
lblCountCritical.Text = $"严重:{cC}";
lblCountHigh.Text = $"高危:{cH}";
lblCountMedium.Text = $"中危:{cM}";
lblCountLow.Text = $"低危:{cL}";
lblCountInfo.Text = $"信息:{cI}";
}
void BtnStart_Click(object? sender, EventArgs e)
{
// 授权二次校验
if (!Licensing.IsRegistered() && Licensing.RemainingTrialDays() <= 0)
{
MessageBox.Show("试用期已结束,请先注册。\r\n联系人:小马 电话/微信:15812096485", "未授权", MessageBoxButtons.OK, MessageBoxIcon.Warning);
tabs.SelectedTab = pageRegister;
return;
}
var targets = CollectTargets();
if (targets.Count == 0) { MessageBox.Show("请先输入目标 URL", "提示"); return; }
// 把所有 {host} 模板替换成实际目标地址
var firstHost = targets[0].Host;
txtLoginUrl.Text = txtLoginUrl.Text.Replace("{host}", firstHost);
txtPostTargets.Text = txtPostTargets.Text.Replace("{host}", firstHost);
var opts = BuildOptions();
_engine = new ScanEngine(opts, targets);
// 扫描线程只往队列塞,不碰UI
_engine.Log = msg => _pendingLogs.Enqueue(msg);
_engine.FindingFound = f =>
{
// 自动补充利用方法和修复建议
var (exploit, remedy) = AdviceProvider.Get(f);
f.Exploitation = exploit;
f.Remediation = remedy;
_pendingFindings.Enqueue(f);
};
_engine.ProgressChanged = p => { _progressTotal = p.Total; _progressCompleted = p.Completed; _progressFindings = p.Findings; };
_engine.ScanFinished = () =>
{
_scanRunning = false;
try { this.BeginInvoke(() =>
{
btnStart.Enabled = true;
btnStop.Enabled = false;
lblStatus.Text = "扫描完成";
_pendingLogs.Enqueue("=== 扫描完成 ===");
}); } catch { }
};
// 清旧数据(UI线程操作)
lock (_lock) { _findings.Clear(); }
resultGrid.Rows.Clear();
UpdateStatus();
progressBar.Value = 0;
_progressTotal = _progressCompleted = _progressFindings = 0;
lblStatus.Text = "扫描中...";
btnStart.Enabled = false;
btnStop.Enabled = true;
_scanRunning = true;
tabs.SelectedIndex = 1;
_ = Task.Run(async () => await _engine.RunAsync());
}
void BtnStop_Click(object? sender, EventArgs e)
{
_engine?.Stop();
lblStatus.Text = "正在停止...";
}
void BtnClearResult_Click(object? sender, EventArgs e)
{
lock (_lock) { _findings.Clear(); }
resultGrid.Rows.Clear();
UpdateStatus();
}
void ResultGrid_DoubleClick(object? sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0) return;
var f = resultGrid.Rows[e.RowIndex].Tag as Finding;
if (f == null) return;
using var dlg = new Form
{
Text = f.Name,
Size = new Size(700, 550),
StartPosition = FormStartPosition.CenterParent,
BackColor = Color.FromArgb(13, 21, 38),
ForeColor = Color.FromArgb(215, 226, 244),
Font = new Font("Microsoft YaHei UI", 10F),
};
var tb = new RichTextBox
{
Dock = DockStyle.Fill,
ReadOnly = true,
BackColor = Color.FromArgb(12, 20, 36),
ForeColor = Color.FromArgb(215, 226, 244),
BorderStyle = BorderStyle.None,
Font = new Font("Microsoft YaHei UI", 10F),
};
tb.Text = $"等级: {f.Severity.Display()}\r\n模块: {f.Module}\r\n目标: {f.Target}\r\nURL: {f.Url}\r\n"
$"时间: {f.Time:yyyy-MM-dd HH:mm:ss}\r\n\r\n详情:\r{f.Detail}\r\n\r\n证据:\r{f.Evidence}\r\n\r\n"
$"利用方法:\r{f.Exploitation}\r\n\r\n修复建议:\r{f.Remediation}";
dlg.Controls.Add(tb);
dlg.ShowDialog(this);
}
List<ScanTarget> CollectTargets()
{
var list = new List<ScanTarget>();
foreach (var part in txtTarget.Text.Split(',', '\n'))
{
var u = part.Trim();
if (u.Length == 0) continue;
try { ScanTarget.NormalizeUrl(u); list.Add(new ScanTarget { Url = u, Enabled = true }); }
catch { }
}
return list;
}
ScanOptions BuildOptions()
{
var o = new ScanOptions
{
MaxConcurrency = (int)nudConcurrency.Value,
TimeoutSeconds = (int)nudTimeout.Value,
ConnectTimeoutMs = (int)nudConnectTimeout.Value,
UserAgent = txtUserAgent.Text,
Proxy = txtProxy.Text,
FollowRedirect = chkRedirect.Checked,
Users = txtUsers.Text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries),
Passwords = txtPasswords.Text.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries),
WeakAuthConcurrency = (int)nudWeakConcurrency.Value,
UsersFile = txtUsersFile.Text,
PasswordsFile = txtPasswordsFile.Text,
LoginUrlTemplate = txtLoginUrl.Text,
UsernameField = txtUserField.Text,
PasswordField = txtPassField.Text,
LoginSuccessKeywords = txtOkWords.Text,
LoginFailKeywords = txtFailWords.Text,
LoginExtraFields = txtExtraFields.Text,
DirWordlistPath = txtDirList.Text,
ServicePorts = txtServicePorts.Text,
ExtraPorts = txtExtraPorts.Text,
PostTestTargets = txtPostTargets.Text,
};
if (chkModules.Items.Count >= 32)
{
o.EnableSqlInjection = chkModules.GetItemChecked(0);
o.EnableHttpBasicWeak = chkModules.GetItemChecked(1);
o.EnableFormLoginWeak = chkModules.GetItemChecked(2);
o.EnableServiceWeak = chkModules.GetItemChecked(3);
o.EnableDirectoryScan = chkModules.GetItemChecked(4);
o.EnablePortScan = chkModules.GetItemChecked(5);
o.EnableXss = chkModules.GetItemChecked(6);
o.EnableInfoGather = chkModules.GetItemChecked(7);
o.EnableSensitive = chkModules.GetItemChecked(8);
o.EnableCommandInjection = chkModules.GetItemChecked(9);
o.EnablePathTraversal = chkModules.GetItemChecked(10);
o.EnableSsti = chkModules.GetItemChecked(11);
o.EnableSecurityHeaders = chkModules.GetItemChecked(12);
o.EnableCors = chkModules.GetItemChecked(13);
o.EnableSmbShare = chkModules.GetItemChecked(14);
o.EnableUnauthorizedAccess = chkModules.GetItemChecked(15);
o.EnableHttpMethod = chkModules.GetItemChecked(16);
o.EnableSsrf = chkModules.GetItemChecked(17);
o.EnableXxe = chkModules.GetItemChecked(18);
o.EnableOpenRedirect = chkModules.GetItemChecked(19);
o.EnableJwt = chkModules.GetItemChecked(20);
o.EnableCrlf = chkModules.GetItemChecked(21);
o.EnableFileUpload = chkModules.GetItemChecked(22);
o.EnableDeserialization = chkModules.GetItemChecked(23);
o.EnableIdor = chkModules.GetItemChecked(24);
o.EnableCsrf = chkModules.GetItemChecked(25);
o.EnableHttpSmuggling = chkModules.GetItemChecked(26);
o.EnableGraphQL = chkModules.GetItemChecked(27);
o.EnableWebDav = chkModules.GetItemChecked(28);
o.EnableSubdomainTakeover = chkModules.GetItemChecked(29);
o.EnableTls = chkModules.GetItemChecked(30);
o.EnableWaf = chkModules.GetItemChecked(31);
}
return o;
}
void BtnExportHtml_Click(object? sender, EventArgs e)
{
using var dlg = new SaveFileDialog { Filter = "HTML|*.html", FileName = $"vuln_report_{DateTime.Now:yyyyMMdd_HHmmss}.html" };
if (dlg.ShowDialog() != DialogResult.OK) return;
btnExportHtml.Enabled = false;
lblStatus.Text = "正在导出HTML...";
var findings = _findings.ToList();
var targets = CollectTargets();
var opts = BuildOptions();
var path = dlg.FileName;
_ = Task.Run(() =>
{
try
{
ReportExporter.ExportHtml(path, findings, targets, opts);
this.BeginInvoke(() => { btnExportHtml.Enabled = true; lblStatus.Text = "HTML已导出"; MessageBox.Show("HTML 报告已导出", "完成"); });
}
catch (Exception ex)
{
this.BeginInvoke(() => { btnExportHtml.Enabled = true; lblStatus.Text = "导出失败"; MessageBox.Show("导出失败: " ex.Message, "错误"); });
}
});
}
void BtnExportCsv_Click(object? sender, EventArgs e)
{
using var dlg = new SaveFileDialog { Filter = "CSV|*.csv", FileName = $"vuln_report_{DateTime.Now:yyyyMMdd_HHmmss}.csv" };
if (dlg.ShowDialog() != DialogResult.OK) return;
btnExportCsv.Enabled = false;
lblStatus.Text = "正在导出CSV...";
var findings = _findings.ToList();
var path = dlg.FileName;
_ = Task.Run(() =>
{
try
{
ReportExporter.ExportCsv(path, findings);
this.BeginInvoke(() => { btnExportCsv.Enabled = true; lblStatus.Text = "CSV已导出"; MessageBox.Show("CSV 报告已导出", "完成"); });
}
catch (Exception ex)
{
this.BeginInvoke(() => { btnExportCsv.Enabled = true; lblStatus.Text = "导出失败"; MessageBox.Show("导出失败: " ex.Message, "错误"); });
}
});
}
async Task RunDemo(string url)
{
txtTarget.Text = url;
await Task.Delay(500);
BtnStart_Click(null, EventArgs.Empty);
}
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论