mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-02-09 10:19:19 +08:00
## 架构重构
- 全局变量消除,迁移至 Config/State 对象
- SMB 插件融合(smb/smb2/smbghost/smbinfo)
- 服务探测重构,实现 Nmap 风格 fallback 机制
- 输出系统重构,TXT 实时刷盘 + 双写机制
- i18n 框架升级至 go-i18n
## 性能优化
- 正则表达式预编译
- 内存优化 map[string]struct{}
- 并发指纹匹配
- SOCKS5 连接复用
- 滑动窗口调度 + 自适应线程池
## 新功能
- Web 管理界面
- 多格式 POC 适配(xray/afrog)
- 增强指纹库(3139条)
- Favicon hash 指纹识别
- 插件选择性编译(Build Tags)
- fscan-lab 靶场环境
- 默认端口扩展(62→133)
## 构建系统
- 添加 no_local tag 支持排除本地插件
- 多版本构建:fscan/fscan-nolocal/fscan-web
- CI 添加 snapshot 模式支持仅测试构建
## Bug 修复
- 修复 120+ 个问题,包括 RDP panic、批量扫描漏报、
JSON 输出格式、Redis 检测、Context 超时等
## 测试增强
- 单元测试覆盖率 74-100%
- 并发安全测试
- 集成测试(Web/端口/服务/SSH/ICMP)
150 lines
5.5 KiB
Python
150 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
fscan 参数测试结果可视化
|
|
"""
|
|
|
|
import csv
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
import os
|
|
|
|
# 设置中文字体
|
|
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei', 'DejaVu Sans']
|
|
plt.rcParams['axes.unicode_minus'] = False
|
|
|
|
def read_csv(filepath):
|
|
results = []
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
reader = csv.DictReader(f)
|
|
for row in reader:
|
|
results.append(row)
|
|
return results
|
|
|
|
def create_charts(output_dir):
|
|
# 读取数据
|
|
time_file = os.path.join(output_dir, "time_results.csv")
|
|
mt_file = os.path.join(output_dir, "mt_results.csv")
|
|
|
|
time_data = read_csv(time_file)
|
|
mt_data = read_csv(mt_file)
|
|
|
|
# 创建图表
|
|
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
|
|
fig.suptitle('fscan 参数性能测试 (目标: 1.1.1.0/24)', fontsize=14, fontweight='bold')
|
|
|
|
# ==================== 图1: -time 超时参数 ====================
|
|
ax1 = axes[0]
|
|
|
|
times = [int(d['time_seconds']) for d in time_data]
|
|
pps = [float(d['packets_per_sec']) for d in time_data]
|
|
duration = [float(d['duration_ms'])/1000 for d in time_data]
|
|
|
|
# 双Y轴
|
|
color1 = '#2ecc71'
|
|
ax1.set_xlabel('超时时间 -time (秒)', fontsize=11)
|
|
ax1.set_ylabel('吞吐量 (pps)', color=color1, fontsize=11)
|
|
bars = ax1.bar([x - 0.2 for x in range(len(times))], pps, 0.4, color=color1, alpha=0.7, label='吞吐量')
|
|
ax1.tick_params(axis='y', labelcolor=color1)
|
|
ax1.set_xticks(range(len(times)))
|
|
ax1.set_xticklabels([f'{t}s' for t in times])
|
|
|
|
# 标注最优值
|
|
max_idx = np.argmax(pps)
|
|
ax1.bar(max_idx - 0.2, pps[max_idx], 0.4, color='#27ae60', alpha=0.9, edgecolor='red', linewidth=2)
|
|
|
|
ax1_twin = ax1.twinx()
|
|
color2 = '#e74c3c'
|
|
ax1_twin.set_ylabel('扫描耗时 (秒)', color=color2, fontsize=11)
|
|
ax1_twin.bar([x + 0.2 for x in range(len(times))], duration, 0.4, color=color2, alpha=0.7, label='耗时')
|
|
ax1_twin.tick_params(axis='y', labelcolor=color2)
|
|
|
|
# 添加数值标签
|
|
for i, (p, d) in enumerate(zip(pps, duration)):
|
|
ax1.text(i - 0.2, p + 2, f'{p:.1f}', ha='center', fontsize=9, color=color1)
|
|
ax1_twin.text(i + 0.2, d + 0.3, f'{d:.1f}s', ha='center', fontsize=9, color=color2)
|
|
|
|
ax1.set_title('-time 超时参数影响\n(默认值: 3秒)', fontsize=12)
|
|
ax1.axhline(y=pps[2], color='gray', linestyle='--', alpha=0.5, label='默认值基准')
|
|
|
|
# 计算相对于默认值的提升
|
|
default_pps = pps[2] # time=3 是默认值
|
|
improvement = [(p - default_pps) / default_pps * 100 for p in pps]
|
|
|
|
# ==================== 图2: -mt 模块线程参数 ====================
|
|
ax2 = axes[1]
|
|
|
|
mts = [int(d['module_threads']) for d in mt_data]
|
|
mt_pps = [float(d['packets_per_sec']) for d in mt_data]
|
|
mt_duration = [float(d['duration_ms'])/1000 for d in mt_data]
|
|
|
|
ax2.bar(range(len(mts)), mt_pps, color='#3498db', alpha=0.7)
|
|
ax2.set_xlabel('模块线程数 -mt', fontsize=11)
|
|
ax2.set_ylabel('吞吐量 (pps)', fontsize=11)
|
|
ax2.set_xticks(range(len(mts)))
|
|
ax2.set_xticklabels(mts)
|
|
ax2.set_title('-mt 模块线程参数影响\n(默认值: 20, 测试时禁用POC)', fontsize=12)
|
|
|
|
# 添加数值标签
|
|
for i, p in enumerate(mt_pps):
|
|
ax2.text(i, p + 0.5, f'{p:.1f}', ha='center', fontsize=9)
|
|
|
|
# 计算变化范围
|
|
mt_range = max(mt_pps) - min(mt_pps)
|
|
ax2.set_ylim(min(mt_pps) - 5, max(mt_pps) + 5)
|
|
|
|
# 添加注释
|
|
ax2.text(0.5, 0.95, f'变化幅度: {mt_range:.2f} pps (可忽略)',
|
|
transform=ax2.transAxes, ha='center', fontsize=10,
|
|
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
|
|
|
|
plt.tight_layout()
|
|
|
|
output_path = os.path.join(output_dir, 'param_test_chart.png')
|
|
plt.savefig(output_path, dpi=150, bbox_inches='tight')
|
|
print(f"图表已保存: {output_path}")
|
|
plt.close()
|
|
|
|
# ==================== 生成详细分析图 ====================
|
|
fig2, ax = plt.subplots(figsize=(10, 6))
|
|
|
|
x = np.arange(len(times))
|
|
width = 0.35
|
|
|
|
# 性能提升百分比
|
|
colors = ['#e74c3c' if imp < 0 else '#2ecc71' for imp in improvement]
|
|
bars = ax.bar(x, improvement, width, color=colors, alpha=0.8)
|
|
|
|
ax.axhline(y=0, color='black', linestyle='-', linewidth=0.5)
|
|
ax.set_xlabel('超时时间 -time (秒)', fontsize=12)
|
|
ax.set_ylabel('相对默认值(3秒)的性能变化 (%)', fontsize=12)
|
|
ax.set_title('-time 参数优化效果分析', fontsize=14, fontweight='bold')
|
|
ax.set_xticks(x)
|
|
ax.set_xticklabels([f'{t}s' for t in times])
|
|
|
|
# 添加数值标签
|
|
for i, (bar, imp) in enumerate(zip(bars, improvement)):
|
|
height = bar.get_height()
|
|
ax.text(bar.get_x() + bar.get_width()/2., height + (1 if height >= 0 else -3),
|
|
f'{imp:+.1f}%', ha='center', va='bottom' if height >= 0 else 'top',
|
|
fontsize=11, fontweight='bold')
|
|
|
|
# 添加建议
|
|
ax.text(0.02, 0.98,
|
|
'建议:\n• 内网环境: -time 1 或 2\n• 公网环境: -time 3 (默认)\n• 高延迟网络: -time 5+',
|
|
transform=ax.transAxes, fontsize=10, verticalalignment='top',
|
|
bbox=dict(boxstyle='round', facecolor='lightyellow', alpha=0.8))
|
|
|
|
plt.tight_layout()
|
|
|
|
output_path2 = os.path.join(output_dir, 'time_optimization_chart.png')
|
|
plt.savefig(output_path2, dpi=150, bbox_inches='tight')
|
|
print(f"图表已保存: {output_path2}")
|
|
plt.close()
|
|
|
|
def main():
|
|
output_dir = "results/param_tests"
|
|
create_charts(output_dir)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|