扫描器解析日记之目标探测
字数 1142 2025-08-20 18:17:59
扫描器目标探测模块解析与实现
1. 目标探测概述
目标探测是扫描器的核心功能之一,主要用于识别网络中存活的主机和开放的端口。本文以fscan、GoGo和dddd三款扫描器为例,详细分析其目标探测模块的实现原理和技术细节。
2. fscan目标探测实现
2.1 IP地址解析
fscan的IP解析逻辑位于ParseIP函数中,主要处理以下几种格式的输入:
func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) {
if filename == "" && strings.Contains(host, ":") {
// 处理带端口的IP格式:192.168.0.0/16:80
hostport := strings.Split(host, ":")
if len(hostport) == 2 {
host = hostport[0]
hosts = ParseIPs(host)
Ports = hostport[1]
}
} else {
hosts = ParseIPs(host)
if filename != "" {
var filehost []string
filehost, _ = Readipfile(filename)
hosts = append(hosts, filehost...)
}
}
// 去重处理
hosts = RemoveDuplicate(hosts)
return
}
2.2 存活探测实现
fscan提供了两种存活探测方式:
2.2.1 ICMP探测
func CheckLive(hostslist []string, Ping bool) []string {
chanHosts := make(chan string, len(hostslist))
go func() {
for ip := range chanHosts {
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
ExistHosts[ip] = struct{}{}
AliveHosts = append(AliveHosts, ip)
}
livewg.Done()
}
}()
// ...
}
2.2.2 TCP端口探测
func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) {
host, port := addr.ip, addr.port
conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port),
time.Duration(adjustedTimeout)*time.Second)
if err == nil {
defer conn.Close()
address := host + ":" + strconv.Itoa(port)
respondingHosts <- address
}
}
2.3 大网段扫描优化
fscan对大网段(/8)扫描进行了优化,避免扫描过多IP:
func parseIP8(ip string) []string {
var AllIP []string
for _, i := range CIDRToIP(ip) {
AllIP = append(AllIP, i.String())
}
return AllIP
}
func CIDRToIP(cidr string) (IPs []net.IP) {
_, network, _ := net.ParseCIDR(cidr)
first := FirstIP(network)
last := LastIP(network)
return pairsToIP(first, last)
}
3. GoGo目标探测实现
3.1 端口扫描分发
GoGo通过Dispatch函数根据端口号分发不同的扫描逻辑:
func Dispatch(result *pkg.Result) {
switch result.Port {
case "137", "nbt":
nbtScan(result)
case "135", "wmi":
wmiScan(result)
case "oxid":
oxidScan(result)
case "icmp", "ping":
icmpScan(result)
case "snmp", "161":
snmpScan(result)
case "445", "smb":
smbScan(result)
// ...其他端口处理
default:
initScan(result)
}
}
3.2 基础TCP扫描
func initScan(result *pkg.Result) {
conn, err := pkg.NewSocket("tcp", target, RunOpt.Delay)
if err != nil {
result.Err = err
return
}
defer conn.Close()
result.Open = true
bs, err := conn.Read(RunOpt.Delay)
if err != nil {
senddataStr := fmt.Sprintf("GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", result.Uri, target)
bs, err = conn.Request([]byte(senddataStr), DefaultMaxSize)
}
pkg.CollectSocketResponse(result, bs)
}
4. dddd目标探测实现
4.1 多阶段探测
dddd采用多阶段探测策略:
// ICMP探测存活
if !structs.GlobalConfig.NoICMPPing {
ICMPAlive = common.CheckLive(ips, false)
}
// TCP探测存活
if structs.GlobalConfig.TCPPing {
tcpAliveIPPort := common.PortScanTCP(uncheck, "80,443,3389,445,22",
structs.GlobalConfig.NoPortString,
structs.GlobalConfig.TCPPortScanTimeout)
for _, tIPPort := range tcpAliveIPPort {
t := strings.Split(tIPPort, ":")
TCPAlive = append(TCPAlive, t[0])
}
}
4.2 SYN扫描集成
dddd集成了masscan进行SYN扫描:
// 调用masscan进行SYN端口扫描
masscanArgs := []string{
"--ports", ports,
"--rate", strconv.Itoa(structs.GlobalConfig.Rate),
"-oG", outputFile,
}
masscanArgs = append(masscanArgs, ips...)
5. 技术对比与总结
| 特性 | fscan | GoGo | dddd |
|---|---|---|---|
| IP解析 | 支持CIDR、范围、文件输入 | 支持标准格式 | 支持多种格式 |
| 存活探测 | ICMP/TCP | 多协议探测 | ICMP/TCP/SYN |
| 大网段优化 | 随机采样 | 无特别优化 | 无特别优化 |
| 端口扫描 | 基础TCP连接 | 协议识别+定制扫描 | SYN扫描集成 |
| 代理支持 | 支持SOCKS5 | 支持HTTP/SOCKS | 支持多种代理 |
6. 最佳实践建议
-
IP解析优化:
- 实现CIDR到IP列表的高效转换
- 对大网段(/8)采用采样策略
- 支持多种输入格式(文件、范围、CIDR)
-
存活探测策略:
- 优先使用ICMP探测
- 对ICMP无响应主机尝试TCP探测
- 关键端口(80,443,22,3389等)作为补充
-
扫描性能优化:
- 使用goroutine和channel实现并发
- 合理设置超时时间
- 实现结果去重和状态管理
-
协议识别:
- 对常见端口实现定制化探测
- 自动识别HTTP/HTTPS服务
- 支持特殊协议(如WMI、SNMP等)
7. 参考实现
// 综合扫描器示例
func AdvancedScan(targets []string) {
// 阶段1:ICMP存活探测
aliveHosts := ICMPProbe(targets)
// 阶段2:TCP端口扫描
openPorts := TCPScan(aliveHosts, "80,443,22,3389,445")
// 阶段3:服务识别
for host, ports := range openPorts {
for _, port := range ports {
switch port {
case 80, 443:
result := HTTPProbe(host, port)
case 445:
result := SMBProbe(host)
// 其他端口处理...
}
}
}
}
8. 参考文献
- fscan源码: https://github.com/shadow1ng/fscan
- GoGo文档: https://chainreactors.github.io/wiki/gogo
- dddd源码: https://github.com/SleepingBag945/dddd
- 网络扫描技术详解: https://xz.aliyun.com/t/15318