---
title: vidar-scan开发日志-2
date: 2026-04-01 19:58:26
tags: [golang,开发]
---
突然想起还没写后续,回忆着写一下
继上次路径爆破功能介绍后,我记忆中更新的内容。。。
路径爆破部分
在原来只是通过响应码识别的基础上,加入了 404page 的识别模型,也就是我们常说的 ai 赋能
1 | |
很可惜,这部分是朋友写的,我只负责用,不是很懂,但是好歹也是解决了一些大网站存在的软 404 页面
端口扫描
之后重点应该转到端口扫描上来了,一开始我想着,端口扫描不就是给一个个端口发包么,和路径爆破应该差别不大,之后经过一番了解和学长的指导,了解到不需要建立完整的 tcp 握手,只需要发送 syn 包探活即可
很显然现在不能直接用 client.Do 发个 http 包了,大致流程如下
- 路由查询:调用
routing.New()读取内核路由表,然后router.Route(dst)确定访问目标 IP 时使用的网卡接口(iface)、网关(gw)和源 IP(srcIP) - 获取网卡对象:
net.InterfaceByName(iface.Name)拿到完整网卡信息,包括 MAC 地址 - 打开 pcap 句柄:
pcap.OpenLive(iface.Name, 65535, false, pcap.BlockForever)打开原始抓包/发包句柄 - ARP 解析目标 MAC:调用
resolveMAC(handle, ifaceObj, srcIP, nextHop)——构造 ARP Request 广播包,发出后等待 ARP Reply,从中提取下一跳的 MAC 地址(如果有网关就解析网关 MAC,否则解析目标主机 MAC) - 设置 BPF 过滤器:
tcp and src host <dst> and dst host <srcIP> and dst port <srcPort>,只捕获从目标返回的、目的端口为 56789 的 TCP 包 - 启动监听协程:
go s.listenReply()在后台持续读包
设置 worker,每个 worker 负责一个端口,通过令牌桶控制发包速率 basework.Limiter.Wait(context.Background()),且每个 worker 完成一个任务后 “休息” 1000ms
逐层构造原始 SYN 包
- 以太网层:
layers.Ethernet{SrcMAC, DstMAC, EthernetTypeIPv4} - IP 层:
layers.IPv4{Version:4, IHL:5, TTL:64, Protocol:TCP, SrcIP, DstIP} - TCP 层:
layers.TCP{SrcPort:56789, DstPort:目标端口, SYN:true, Window:14600} - 计算校验和:
tcp.SetNetworkLayerForChecksum(ip4)让 gopacket 根据 IP 伪首部自动计算 TCP 校验和 - 序列化:
gopacket.SerializeLayers(buf, opts, eth, ip4, tcp),开启FixLengths和ComputeChecksums - 发送:
s.handle.WritePacketData(buf.Bytes())通过 pcap 句柄直接写入网卡
之后就是发包后等待回包,判断标志位:SYN+ACK → "open",RST → "close" 这里,把超时也视为 close 处理(原来一直在和超时较劲,之后学长告知相关内容,仿制在扫描器中超时和 close 几乎是一回事)所以,设置一个最大等待时间,不会一直等待
在一开始,我使用的是并发控制,之后改为了并发控制和速率控制一起,所以写了个自适应速率控制器,因为要考虑到目标服务器的性能,本机的性能,不能瞬发巨量包
每个 worker 完成任务后上传信息
1 | |
此处,只有出现在 open close timeout 外的状态才会算作异常 err
此处,限制速率的具体实现是一个令牌桶,每个 worker 的任务中会有一个 Wait,只有令牌桶中有令牌时,才可以拿到令牌去运行
自适应速率的实现比较粗糙,还有待改进
1 | |
以及什么 retry 机制就不多说了
漏扫模块
本模块比较简单,依旧是传统那套依据 yaml 文件发包,多的部分可能是可以通过编辑 yaml 中加入某个字段实现获取想要的信息,其他没什么太多变化,说一下有这么个东西,但还不是很成熟