CN to EN from Core

This commit is contained in:
Budi Komarudin 2025-03-19 10:31:08 +00:00
parent 968064c240
commit 50a53e1fd8
6 changed files with 616 additions and 616 deletions

View File

@ -14,38 +14,38 @@ import (
) )
var ( var (
AliveHosts []string // 存活主机列表 AliveHosts []string // List of alive hosts
ExistHosts = make(map[string]struct{}) // 已发现主机记录 ExistHosts = make(map[string]struct{}) // Record of discovered hosts
livewg sync.WaitGroup // 存活检测等待组 livewg sync.WaitGroup // Wait group for live detection
) )
// CheckLive 检测主机存活状态 // CheckLive checks the live status of hosts
func CheckLive(hostslist []string, Ping bool) []string { func CheckLive(hostslist []string, Ping bool) []string {
// 创建主机通道 // Create host channel
chanHosts := make(chan string, len(hostslist)) chanHosts := make(chan string, len(hostslist))
// 处理存活主机 // Handle alive hosts
go handleAliveHosts(chanHosts, hostslist, Ping) go handleAliveHosts(chanHosts, hostslist, Ping)
// 根据Ping参数选择检测方式 // Choose detection method based on Ping parameter
if Ping { if Ping {
// 使用ping方式探测 // Use ping method
RunPing(hostslist, chanHosts) RunPing(hostslist, chanHosts)
} else { } else {
probeWithICMP(hostslist, chanHosts) probeWithICMP(hostslist, chanHosts)
} }
// 等待所有检测完成 // Wait for all detections to complete
livewg.Wait() livewg.Wait()
close(chanHosts) close(chanHosts)
// 输出存活统计信息 // Print alive statistics
printAliveStats(hostslist) printAliveStats(hostslist)
return AliveHosts return AliveHosts
} }
// IsContain 检查切片中是否包含指定元素 // IsContain checks if the slice contains the specified element
func IsContain(items []string, item string) bool { func IsContain(items []string, item string) bool {
for _, eachItem := range items { for _, eachItem := range items {
if eachItem == item { if eachItem == item {
@ -61,7 +61,7 @@ func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
ExistHosts[ip] = struct{}{} ExistHosts[ip] = struct{}{}
AliveHosts = append(AliveHosts, ip) AliveHosts = append(AliveHosts, ip)
// 使用Output系统保存存活主机信息 // Use Output system to save alive host information
protocol := "ICMP" protocol := "ICMP"
if isPing { if isPing {
protocol = "PING" protocol = "PING"
@ -78,7 +78,7 @@ func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
} }
Common.SaveResult(result) Common.SaveResult(result)
// 保留原有的控制台输出 // Keep original console output
if !Common.Silent { if !Common.Silent {
Common.LogSuccess(Common.GetText("target_alive", ip, protocol)) Common.LogSuccess(Common.GetText("target_alive", ip, protocol))
} }
@ -87,9 +87,9 @@ func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
} }
} }
// probeWithICMP 使用ICMP方式探测 // probeWithICMP probes using ICMP method
func probeWithICMP(hostslist []string, chanHosts chan string) { func probeWithICMP(hostslist []string, chanHosts chan string) {
// 尝试监听本地ICMP // Try to listen on local ICMP
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err == nil { if err == nil {
RunIcmp1(hostslist, conn, chanHosts) RunIcmp1(hostslist, conn, chanHosts)
@ -99,7 +99,7 @@ func probeWithICMP(hostslist []string, chanHosts chan string) {
Common.LogError(Common.GetText("icmp_listen_failed", err)) Common.LogError(Common.GetText("icmp_listen_failed", err))
Common.LogInfo(Common.GetText("trying_no_listen_icmp")) Common.LogInfo(Common.GetText("trying_no_listen_icmp"))
// 尝试无监听ICMP探测 // Try no-listen ICMP probe
conn2, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second) conn2, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second)
if err == nil { if err == nil {
defer conn2.Close() defer conn2.Close()
@ -111,22 +111,22 @@ func probeWithICMP(hostslist []string, chanHosts chan string) {
Common.LogInfo(Common.GetText("insufficient_privileges")) Common.LogInfo(Common.GetText("insufficient_privileges"))
Common.LogInfo(Common.GetText("switching_to_ping")) Common.LogInfo(Common.GetText("switching_to_ping"))
// 降级使用ping探测 // Fallback to ping probe
RunPing(hostslist, chanHosts) RunPing(hostslist, chanHosts)
} }
// printAliveStats 打印存活统计信息 // printAliveStats prints alive statistics
func printAliveStats(hostslist []string) { func printAliveStats(hostslist []string) {
// 大规模扫描时输出 /16 网段统计 // Output /16 subnet statistics for large-scale scans
if len(hostslist) > 1000 { if (len(hostslist) > 1000) {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, true) arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, true)
for i := 0; i < len(arrTop); i++ { for i := 0; i < len(arrTop); i++ {
Common.LogSuccess(Common.GetText("subnet_16_alive", arrTop[i], arrLen[i])) Common.LogSuccess(Common.GetText("subnet_16_alive", arrTop[i], arrLen[i]))
} }
} }
// 输出 /24 网段统计 // Output /24 subnet statistics
if len(hostslist) > 256 { if (len(hostslist) > 256) {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, false) arrTop, arrLen := ArrayCountValueTop(AliveHosts, Common.LiveTop, false)
for i := 0; i < len(arrTop); i++ { for i := 0; i < len(arrTop); i++ {
Common.LogSuccess(Common.GetText("subnet_24_alive", arrTop[i], arrLen[i])) Common.LogSuccess(Common.GetText("subnet_24_alive", arrTop[i], arrLen[i]))
@ -134,17 +134,17 @@ func printAliveStats(hostslist []string) {
} }
} }
// RunIcmp1 使用ICMP批量探测主机存活(监听模式) // RunIcmp1 uses ICMP to probe host liveliness (listen mode)
func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string) { func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string) {
endflag := false endflag := false
// 启动监听协程 // Start listening goroutine
go func() { go func() {
for { for {
if endflag { if endflag {
return return
} }
// 接收ICMP响应 // Receive ICMP response
msg := make([]byte, 100) msg := make([]byte, 100)
_, sourceIP, _ := conn.ReadFrom(msg) _, sourceIP, _ := conn.ReadFrom(msg)
if sourceIP != nil { if sourceIP != nil {
@ -154,22 +154,22 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string)
} }
}() }()
// 发送ICMP请求 // Send ICMP requests
for _, host := range hostslist { for _, host := range hostslist {
dst, _ := net.ResolveIPAddr("ip", host) dst, _ := net.ResolveIPAddr("ip", host)
IcmpByte := makemsg(host) IcmpByte := makemsg(host)
conn.WriteTo(IcmpByte, dst) conn.WriteTo(IcmpByte, dst)
} }
// 等待响应 // Wait for responses
start := time.Now() start := time.Now()
for { for {
// 所有主机都已响应则退出 // Exit if all hosts have responded
if len(AliveHosts) == len(hostslist) { if len(AliveHosts) == len(hostslist) {
break break
} }
// 根据主机数量设置超时时间 // Set timeout based on number of hosts
since := time.Since(start) since := time.Since(start)
wait := time.Second * 6 wait := time.Second * 6
if len(hostslist) <= 256 { if len(hostslist) <= 256 {
@ -185,9 +185,9 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string)
conn.Close() conn.Close()
} }
// RunIcmp2 使用ICMP并发探测主机存活(无监听模式) // RunIcmp2 uses ICMP to probe host liveliness (no-listen mode)
func RunIcmp2(hostslist []string, chanHosts chan string) { func RunIcmp2(hostslist []string, chanHosts chan string) {
// 控制并发数 // Control concurrency
num := 1000 num := 1000
if len(hostslist) < num { if len(hostslist) < num {
num = len(hostslist) num = len(hostslist)
@ -196,7 +196,7 @@ func RunIcmp2(hostslist []string, chanHosts chan string) {
var wg sync.WaitGroup var wg sync.WaitGroup
limiter := make(chan struct{}, num) limiter := make(chan struct{}, num)
// 并发探测 // Concurrent probing
for _, host := range hostslist { for _, host := range hostslist {
wg.Add(1) wg.Add(1)
limiter <- struct{}{} limiter <- struct{}{}
@ -218,29 +218,29 @@ func RunIcmp2(hostslist []string, chanHosts chan string) {
close(limiter) close(limiter)
} }
// icmpalive 检测主机ICMP是否存活 // icmpalive checks if the host is alive using ICMP
func icmpalive(host string) bool { func icmpalive(host string) bool {
startTime := time.Now() startTime := time.Now()
// 建立ICMP连接 // Establish ICMP connection
conn, err := net.DialTimeout("ip4:icmp", host, 6*time.Second) conn, err := net.DialTimeout("ip4:icmp", host, 6*time.Second)
if err != nil { if err != nil {
return false return false
} }
defer conn.Close() defer conn.Close()
// 设置超时时间 // Set timeout
if err := conn.SetDeadline(startTime.Add(6 * time.Second)); err != nil { if err := conn.SetDeadline(startTime.Add(6 * time.Second)); err != nil {
return false return false
} }
// 构造并发送ICMP请求 // Construct and send ICMP request
msg := makemsg(host) msg := makemsg(host)
if _, err := conn.Write(msg); err != nil { if _, err := conn.Write(msg); err != nil {
return false return false
} }
// 接收ICMP响应 // Receive ICMP response
receive := make([]byte, 60) receive := make([]byte, 60)
if _, err := conn.Read(receive); err != nil { if _, err := conn.Read(receive); err != nil {
return false return false
@ -249,13 +249,13 @@ func icmpalive(host string) bool {
return true return true
} }
// RunPing 使用系统Ping命令并发探测主机存活 // RunPing uses system ping command to probe host liveliness concurrently
func RunPing(hostslist []string, chanHosts chan string) { func RunPing(hostslist []string, chanHosts chan string) {
var wg sync.WaitGroup var wg sync.WaitGroup
// 限制并发数为50 // Limit concurrency to 50
limiter := make(chan struct{}, 50) limiter := make(chan struct{}, 50)
// 并发探测 // Concurrent probing
for _, host := range hostslist { for _, host := range hostslist {
wg.Add(1) wg.Add(1)
limiter <- struct{}{} limiter <- struct{}{}
@ -276,9 +276,9 @@ func RunPing(hostslist []string, chanHosts chan string) {
wg.Wait() wg.Wait()
} }
// ExecCommandPing 执行系统Ping命令检测主机存活 // ExecCommandPing executes system ping command to check host liveliness
func ExecCommandPing(ip string) bool { func ExecCommandPing(ip string) bool {
// 过滤黑名单字符 // Filter blacklist characters
forbiddenChars := []string{";", "&", "|", "`", "$", "\\", "'", "%", "\"", "\n"} forbiddenChars := []string{";", "&", "|", "`", "$", "\\", "'", "%", "\"", "\n"}
for _, char := range forbiddenChars { for _, char := range forbiddenChars {
if strings.Contains(ip, char) { if strings.Contains(ip, char) {
@ -287,7 +287,7 @@ func ExecCommandPing(ip string) bool {
} }
var command *exec.Cmd var command *exec.Cmd
// 根据操作系统选择不同的ping命令 // Choose different ping commands based on OS
switch runtime.GOOS { switch runtime.GOOS {
case "windows": case "windows":
command = exec.Command("cmd", "/c", "ping -n 1 -w 1 "+ip+" && echo true || echo false") command = exec.Command("cmd", "/c", "ping -n 1 -w 1 "+ip+" && echo true || echo false")
@ -297,11 +297,11 @@ func ExecCommandPing(ip string) bool {
command = exec.Command("/bin/bash", "-c", "ping -c 1 -w 1 "+ip+" && echo true || echo false") command = exec.Command("/bin/bash", "-c", "ping -c 1 -w 1 "+ip+" && echo true || echo false")
} }
// 捕获命令输出 // Capture command output
var outinfo bytes.Buffer var outinfo bytes.Buffer
command.Stdout = &outinfo command.Stdout = &outinfo
// 执行命令 // Execute command
if err := command.Start(); err != nil { if err := command.Start(); err != nil {
return false return false
} }
@ -310,76 +310,76 @@ func ExecCommandPing(ip string) bool {
return false return false
} }
// 分析输出结果 // Analyze output result
output := outinfo.String() output := outinfo.String()
return strings.Contains(output, "true") && strings.Count(output, ip) > 2 return strings.Contains(output, "true") && strings.Count(output, ip) > 2
} }
// makemsg 构造ICMP echo请求消息 // makemsg constructs ICMP echo request message
func makemsg(host string) []byte { func makemsg(host string) []byte {
msg := make([]byte, 40) msg := make([]byte, 40)
// 获取标识符 // Get identifier
id0, id1 := genIdentifier(host) id0, id1 := genIdentifier(host)
// 设置ICMP头部 // Set ICMP header
msg[0] = 8 // Type: Echo Request msg[0] = 8 // Type: Echo Request
msg[1] = 0 // Code: 0 msg[1] = 0 // Code: 0
msg[2] = 0 // Checksum高位(待计算) msg[2] = 0 // Checksum high byte (to be calculated)
msg[3] = 0 // Checksum低位(待计算) msg[3] = 0 // Checksum low byte (to be calculated)
msg[4], msg[5] = id0, id1 // Identifier msg[4], msg[5] = id0, id1 // Identifier
msg[6], msg[7] = genSequence(1) // Sequence Number msg[6], msg[7] = genSequence(1) // Sequence Number
// 计算校验和 // Calculate checksum
check := checkSum(msg[0:40]) check := checkSum(msg[0:40])
msg[2] = byte(check >> 8) // 设置校验和高位 msg[2] = byte(check >> 8) // Set checksum high byte
msg[3] = byte(check & 255) // 设置校验和低位 msg[3] = byte(check & 255) // Set checksum low byte
return msg return msg
} }
// checkSum 计算ICMP校验和 // checkSum calculates ICMP checksum
func checkSum(msg []byte) uint16 { func checkSum(msg []byte) uint16 {
sum := 0 sum := 0
length := len(msg) length := len(msg)
// 按16位累加 // Accumulate in 16-bit units
for i := 0; i < length-1; i += 2 { for i := 0; i < length-1; i += 2 {
sum += int(msg[i])*256 + int(msg[i+1]) sum += int(msg[i])*256 + int(msg[i+1])
} }
// 处理奇数长度情况 // Handle odd length case
if length%2 == 1 { if length%2 == 1 {
sum += int(msg[length-1]) * 256 sum += int(msg[length-1]) * 256
} }
// 将高16位加到低16位 // Add high 16 bits to low 16 bits
sum = (sum >> 16) + (sum & 0xffff) sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16) sum = sum + (sum >> 16)
// 取反得到校验和 // Take one's complement to get checksum
return uint16(^sum) return uint16(^sum)
} }
// genSequence 生成ICMP序列号 // genSequence generates ICMP sequence number
func genSequence(v int16) (byte, byte) { func genSequence(v int16) (byte, byte) {
ret1 := byte(v >> 8) // 高8位 ret1 := byte(v >> 8) // High 8 bits
ret2 := byte(v & 255) // 低8位 ret2 := byte(v & 255) // Low 8 bits
return ret1, ret2 return ret1, ret2
} }
// genIdentifier 根据主机地址生成标识符 // genIdentifier generates identifier based on host address
func genIdentifier(host string) (byte, byte) { func genIdentifier(host string) (byte, byte) {
return host[0], host[1] // 使用主机地址前两个字节 return host[0], host[1] // Use first two bytes of host address
} }
// ArrayCountValueTop 统计IP地址段存活数量并返回TOP N结果 // ArrayCountValueTop counts the number of alive IP segments and returns the top N results
func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []string, arrLen []int) { func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []string, arrLen []int) {
if len(arrInit) == 0 { if len(arrInit) == 0 {
return return
} }
// 统计各网段出现次数 // Count occurrences of each segment
segmentCounts := make(map[string]int) segmentCounts := make(map[string]int)
for _, ip := range arrInit { for _, ip := range arrInit {
segments := strings.Split(ip, ".") segments := strings.Split(ip, ".")
@ -387,29 +387,29 @@ func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []strin
continue continue
} }
// 根据flag确定统计B段还是C段 // Determine whether to count B segment or C segment based on flag
var segment string var segment string
if flag { if flag {
segment = fmt.Sprintf("%s.%s", segments[0], segments[1]) // B segment = fmt.Sprintf("%s.%s", segments[0], segments[1]) // B segment
} else { } else {
segment = fmt.Sprintf("%s.%s.%s", segments[0], segments[1], segments[2]) // C segment = fmt.Sprintf("%s.%s.%s", segments[0], segments[1], segments[2]) // C segment
} }
segmentCounts[segment]++ segmentCounts[segment]++
} }
// 创建副本用于排序 // Create a copy for sorting
sortMap := make(map[string]int) sortMap := make(map[string]int)
for k, v := range segmentCounts { for k, v := range segmentCounts {
sortMap[k] = v sortMap[k] = v
} }
// 获取TOP N结果 // Get top N results
for i := 0; i < length && len(sortMap) > 0; i++ { for i := 0; i < length && len(sortMap) > 0; i++ {
maxSegment := "" maxSegment := ""
maxCount := 0 maxCount := 0
// 查找当前最大值 // Find current maximum value
for segment, count := range sortMap { for segment, count := range sortMap {
if count > maxCount { if count > maxCount {
maxCount = count maxCount = count
@ -417,11 +417,11 @@ func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []strin
} }
} }
// 添加到结果集 // Add to result set
arrTop = append(arrTop, maxSegment) arrTop = append(arrTop, maxSegment)
arrLen = append(arrLen, maxCount) arrLen = append(arrLen, maxCount)
// 从待处理map中删除已处理项 // Remove processed item from map
delete(sortMap, maxSegment) delete(sortMap, maxSegment)
} }

View File

@ -13,7 +13,7 @@ import (
//go:embed nmap-service-probes.txt //go:embed nmap-service-probes.txt
var ProbeString string var ProbeString string
var v VScan // 改为VScan类型而不是指针 var v VScan // Changed to VScan type instead of pointer
type VScan struct { type VScan struct {
Exclude string Exclude string
@ -24,27 +24,27 @@ type VScan struct {
} }
type Probe struct { type Probe struct {
Name string // 探测器名称 Name string // Probe name
Data string // 探测数据 Data string // Probe data
Protocol string // 协议 Protocol string // Protocol
Ports string // 端口范围 Ports string // Port range
SSLPorts string // SSL端口范围 SSLPorts string // SSL port range
TotalWaitMS int // 总等待时间 TotalWaitMS int // Total wait time
TCPWrappedMS int // TCP包装等待时间 TCPWrappedMS int // TCP wrapped wait time
Rarity int // 稀有度 Rarity int // Rarity
Fallback string // 回退探测器名称 Fallback string // Fallback probe name
Matchs *[]Match // 匹配规则列表 Matchs *[]Match // Match rules list
} }
type Match struct { type Match struct {
IsSoft bool // 是否为软匹配 IsSoft bool // Whether it's a soft match
Service string // 服务名称 Service string // Service name
Pattern string // 匹配模式 Pattern string // Match pattern
VersionInfo string // 版本信息格式 VersionInfo string // Version info format
FoundItems []string // 找到的项目 FoundItems []string // Found items
PatternCompiled *regexp.Regexp // 编译后的正则表达式 PatternCompiled *regexp.Regexp // Compiled regular expression
} }
type Directive struct { type Directive struct {
@ -65,43 +65,43 @@ type Extras struct {
} }
func init() { func init() {
Common.LogDebug("开始初始化全局变量") Common.LogDebug("Starting to initialize global variables")
v = VScan{} // 直接初始化VScan结构体 v = VScan{} // Directly initialize VScan struct
v.Init() v.Init()
// 获取并检查 NULL 探测器 // Get and check NULL probe
if nullProbe, ok := v.ProbesMapKName["NULL"]; ok { if nullProbe, ok := v.ProbesMapKName["NULL"]; ok {
Common.LogDebug(fmt.Sprintf("成功获取NULL探测器Data长度: %d", len(nullProbe.Data))) Common.LogDebug(fmt.Sprintf("Successfully obtained NULL probe, Data length: %d", len(nullProbe.Data)))
null = &nullProbe null = &nullProbe
} else { } else {
Common.LogDebug("警告: 未找到NULL探测器") Common.LogDebug("Warning: NULL probe not found")
} }
// 获取并检查 GenericLines 探测器 // Get and check GenericLines probe
if commonProbe, ok := v.ProbesMapKName["GenericLines"]; ok { if commonProbe, ok := v.ProbesMapKName["GenericLines"]; ok {
Common.LogDebug(fmt.Sprintf("成功获取GenericLines探测器Data长度: %d", len(commonProbe.Data))) Common.LogDebug(fmt.Sprintf("Successfully obtained GenericLines probe, Data length: %d", len(commonProbe.Data)))
common = &commonProbe common = &commonProbe
} else { } else {
Common.LogDebug("警告: 未找到GenericLines探测器") Common.LogDebug("Warning: GenericLines probe not found")
} }
Common.LogDebug("全局变量初始化完成") Common.LogDebug("Global variables initialization complete")
} }
// 解析指令语法,返回指令结构 // Parse directive syntax, return directive structure
func (p *Probe) getDirectiveSyntax(data string) (directive Directive) { func (p *Probe) getDirectiveSyntax(data string) (directive Directive) {
Common.LogDebug("开始解析指令语法,输入数据: " + data) Common.LogDebug("Starting to parse directive syntax, input data: " + data)
directive = Directive{} directive = Directive{}
// 查找第一个空格的位置 // Find the position of the first space
blankIndex := strings.Index(data, " ") blankIndex := strings.Index(data, " ")
if blankIndex == -1 { if blankIndex == -1 {
Common.LogDebug("未找到空格分隔符") Common.LogDebug("Space separator not found")
return directive return directive
} }
// 解析各个字段 // Parse each field
directiveName := data[:blankIndex] directiveName := data[:blankIndex]
Flag := data[blankIndex+1 : blankIndex+2] Flag := data[blankIndex+1 : blankIndex+2]
delimiter := data[blankIndex+2 : blankIndex+3] delimiter := data[blankIndex+2 : blankIndex+3]
@ -112,70 +112,70 @@ func (p *Probe) getDirectiveSyntax(data string) (directive Directive) {
directive.Delimiter = delimiter directive.Delimiter = delimiter
directive.DirectiveStr = directiveStr directive.DirectiveStr = directiveStr
Common.LogDebug(fmt.Sprintf("指令解析结果: 名称=%s, 标志=%s, 分隔符=%s, 内容=%s", Common.LogDebug(fmt.Sprintf("Directive parsing result: Name=%s, Flag=%s, Delimiter=%s, Content=%s",
directiveName, Flag, delimiter, directiveStr)) directiveName, Flag, delimiter, directiveStr))
return directive return directive
} }
// 解析探测器信息 // Parse probe information
func (p *Probe) parseProbeInfo(probeStr string) { func (p *Probe) parseProbeInfo(probeStr string) {
Common.LogDebug("开始解析探测器信息,输入字符串: " + probeStr) Common.LogDebug("Starting to parse probe information, input string: " + probeStr)
// 提取协议和其他信息 // Extract protocol and other information
proto := probeStr[:4] proto := probeStr[:4]
other := probeStr[4:] other := probeStr[4:]
// 验证协议类型 // Validate protocol type
if !(proto == "TCP " || proto == "UDP ") { if !(proto == "TCP " || proto == "UDP ") {
errMsg := "探测器协议必须是 TCP 或 UDP" errMsg := "Probe protocol must be TCP or UDP"
Common.LogDebug("错误: " + errMsg) Common.LogDebug("Error: " + errMsg)
panic(errMsg) panic(errMsg)
} }
// 验证其他信息不为空 // Validate other information is not empty
if len(other) == 0 { if len(other) == 0 {
errMsg := "nmap-service-probes - 探测器名称无效" errMsg := "nmap-service-probes - Invalid probe name"
Common.LogDebug("错误: " + errMsg) Common.LogDebug("Error: " + errMsg)
panic(errMsg) panic(errMsg)
} }
// 解析指令 // Parse directive
directive := p.getDirectiveSyntax(other) directive := p.getDirectiveSyntax(other)
// 设置探测器属性 // Set probe attributes
p.Name = directive.DirectiveName p.Name = directive.DirectiveName
p.Data = strings.Split(directive.DirectiveStr, directive.Delimiter)[0] p.Data = strings.Split(directive.DirectiveStr, directive.Delimiter)[0]
p.Protocol = strings.ToLower(strings.TrimSpace(proto)) p.Protocol = strings.ToLower(strings.TrimSpace(proto))
Common.LogDebug(fmt.Sprintf("探测器解析完成: 名称=%s, 数据=%s, 协议=%s", Common.LogDebug(fmt.Sprintf("Probe parsing completed: Name=%s, Data=%s, Protocol=%s",
p.Name, p.Data, p.Protocol)) p.Name, p.Data, p.Protocol))
} }
// 从字符串解析探测器信息 // Parse probe information from string
func (p *Probe) fromString(data string) error { func (p *Probe) fromString(data string) error {
Common.LogDebug("开始解析探测器字符串数据") Common.LogDebug("Starting to parse probe string data")
var err error var err error
// 预处理数据 // Preprocess data
data = strings.TrimSpace(data) data = strings.TrimSpace(data)
lines := strings.Split(data, "\n") lines := strings.Split(data, "\n")
if len(lines) == 0 { if len(lines) == 0 {
return fmt.Errorf("输入数据为空") return fmt.Errorf("Input data is empty")
} }
probeStr := lines[0] probeStr := lines[0]
p.parseProbeInfo(probeStr) p.parseProbeInfo(probeStr)
// 解析匹配规则和其他配置 // Parse match rules and other configurations
var matchs []Match var matchs []Match
for _, line := range lines { for _, line := range lines {
Common.LogDebug("处理行: " + line) Common.LogDebug("Processing line: " + line)
switch { switch {
case strings.HasPrefix(line, "match "): case strings.HasPrefix(line, "match "):
match, err := p.getMatch(line) match, err := p.getMatch(line)
if err != nil { if err != nil {
Common.LogDebug("解析match失败: " + err.Error()) Common.LogDebug("Failed to parse match: " + err.Error())
continue continue
} }
matchs = append(matchs, match) matchs = append(matchs, match)
@ -183,7 +183,7 @@ func (p *Probe) fromString(data string) error {
case strings.HasPrefix(line, "softmatch "): case strings.HasPrefix(line, "softmatch "):
softMatch, err := p.getSoftMatch(line) softMatch, err := p.getSoftMatch(line)
if err != nil { if err != nil {
Common.LogDebug("解析softmatch失败: " + err.Error()) Common.LogDebug("Failed to parse softmatch: " + err.Error())
continue continue
} }
matchs = append(matchs, softMatch) matchs = append(matchs, softMatch)
@ -208,80 +208,80 @@ func (p *Probe) fromString(data string) error {
} }
} }
p.Matchs = &matchs p.Matchs = &matchs
Common.LogDebug(fmt.Sprintf("解析完成,共有 %d 个匹配规则", len(matchs))) Common.LogDebug(fmt.Sprintf("Parsing completed, total of %d match rules", len(matchs)))
return err return err
} }
// 解析端口配置 // Parse port configuration
func (p *Probe) parsePorts(data string) { func (p *Probe) parsePorts(data string) {
p.Ports = data[len("ports")+1:] p.Ports = data[len("ports")+1:]
Common.LogDebug("解析端口: " + p.Ports) Common.LogDebug("Parsing ports: " + p.Ports)
} }
// 解析SSL端口配置 // Parse SSL port configuration
func (p *Probe) parseSSLPorts(data string) { func (p *Probe) parseSSLPorts(data string) {
p.SSLPorts = data[len("sslports")+1:] p.SSLPorts = data[len("sslports")+1:]
Common.LogDebug("解析SSL端口: " + p.SSLPorts) Common.LogDebug("Parsing SSL ports: " + p.SSLPorts)
} }
// 解析总等待时间 // Parse total wait time
func (p *Probe) parseTotalWaitMS(data string) { func (p *Probe) parseTotalWaitMS(data string) {
waitMS, err := strconv.Atoi(strings.TrimSpace(data[len("totalwaitms")+1:])) waitMS, err := strconv.Atoi(strings.TrimSpace(data[len("totalwaitms")+1:]))
if err != nil { if err != nil {
Common.LogDebug("解析总等待时间失败: " + err.Error()) Common.LogDebug("Failed to parse total wait time: " + err.Error())
return return
} }
p.TotalWaitMS = waitMS p.TotalWaitMS = waitMS
Common.LogDebug(fmt.Sprintf("总等待时间: %d ms", waitMS)) Common.LogDebug(fmt.Sprintf("Total wait time: %d ms", waitMS))
} }
// 解析TCP包装等待时间 // Parse TCP wrapped wait time
func (p *Probe) parseTCPWrappedMS(data string) { func (p *Probe) parseTCPWrappedMS(data string) {
wrappedMS, err := strconv.Atoi(strings.TrimSpace(data[len("tcpwrappedms")+1:])) wrappedMS, err := strconv.Atoi(strings.TrimSpace(data[len("tcpwrappedms")+1:]))
if err != nil { if err != nil {
Common.LogDebug("解析TCP包装等待时间失败: " + err.Error()) Common.LogDebug("Failed to parse TCP wrapped wait time: " + err.Error())
return return
} }
p.TCPWrappedMS = wrappedMS p.TCPWrappedMS = wrappedMS
Common.LogDebug(fmt.Sprintf("TCP包装等待时间: %d ms", wrappedMS)) Common.LogDebug(fmt.Sprintf("TCP wrapped wait time: %d ms", wrappedMS))
} }
// 解析稀有度 // Parse rarity
func (p *Probe) parseRarity(data string) { func (p *Probe) parseRarity(data string) {
rarity, err := strconv.Atoi(strings.TrimSpace(data[len("rarity")+1:])) rarity, err := strconv.Atoi(strings.TrimSpace(data[len("rarity")+1:]))
if err != nil { if err != nil {
Common.LogDebug("解析稀有度失败: " + err.Error()) Common.LogDebug("Failed to parse rarity: " + err.Error())
return return
} }
p.Rarity = rarity p.Rarity = rarity
Common.LogDebug(fmt.Sprintf("稀有度: %d", rarity)) Common.LogDebug(fmt.Sprintf("Rarity: %d", rarity))
} }
// 解析回退配置 // Parse fallback configuration
func (p *Probe) parseFallback(data string) { func (p *Probe) parseFallback(data string) {
p.Fallback = data[len("fallback")+1:] p.Fallback = data[len("fallback")+1:]
Common.LogDebug("回退配置: " + p.Fallback) Common.LogDebug("Fallback configuration: " + p.Fallback)
} }
// 判断是否为十六进制编码 // Check if it's a hexadecimal code
func isHexCode(b []byte) bool { func isHexCode(b []byte) bool {
matchRe := regexp.MustCompile(`\\x[0-9a-fA-F]{2}`) matchRe := regexp.MustCompile(`\\x[0-9a-fA-F]{2}`)
return matchRe.Match(b) return matchRe.Match(b)
} }
// 判断是否为八进制编码 // Check if it's an octal code
func isOctalCode(b []byte) bool { func isOctalCode(b []byte) bool {
matchRe := regexp.MustCompile(`\\[0-7]{1,3}`) matchRe := regexp.MustCompile(`\\[0-7]{1,3}`)
return matchRe.Match(b) return matchRe.Match(b)
} }
// 判断是否为结构化转义字符 // Check if it's a structured escape character
func isStructCode(b []byte) bool { func isStructCode(b []byte) bool {
matchRe := regexp.MustCompile(`\\[aftnrv]`) matchRe := regexp.MustCompile(`\\[aftnrv]`)
return matchRe.Match(b) return matchRe.Match(b)
} }
// 判断是否为正则表达式特殊字符 // Check if it's a regular expression special character
func isReChar(n int64) bool { func isReChar(n int64) bool {
reChars := `.*?+{}()^$|\` reChars := `.*?+{}()^$|\`
for _, char := range reChars { for _, char := range reChars {
@ -292,19 +292,19 @@ func isReChar(n int64) bool {
return false return false
} }
// 判断是否为其他转义序列 // Check if it's another escape sequence
func isOtherEscapeCode(b []byte) bool { func isOtherEscapeCode(b []byte) bool {
matchRe := regexp.MustCompile(`\\[^\\]`) matchRe := regexp.MustCompile(`\\[^\\]`)
return matchRe.Match(b) return matchRe.Match(b)
} }
// 从内容解析探测器规则 // Parse probe rules from content
func (v *VScan) parseProbesFromContent(content string) { func (v *VScan) parseProbesFromContent(content string) {
Common.LogDebug("开始解析探测器规则文件内容") Common.LogDebug("Starting to parse probe rules from file content")
var probes []Probe var probes []Probe
var lines []string var lines []string
// 过滤注释和空行 // Filter comments and empty lines
linesTemp := strings.Split(content, "\n") linesTemp := strings.Split(content, "\n")
for _, lineTemp := range linesTemp { for _, lineTemp := range linesTemp {
lineTemp = strings.TrimSpace(lineTemp) lineTemp = strings.TrimSpace(lineTemp)
@ -314,196 +314,196 @@ func (v *VScan) parseProbesFromContent(content string) {
lines = append(lines, lineTemp) lines = append(lines, lineTemp)
} }
// 验证文件内容 // Validate file content
if len(lines) == 0 { if len(lines) == 0 {
errMsg := "读取nmap-service-probes文件失败: 内容为空" errMsg := "Failed to read nmap-service-probes file: Content is empty"
Common.LogDebug("错误: " + errMsg) Common.LogDebug("Error: " + errMsg)
panic(errMsg) panic(errMsg)
} }
// 检查Exclude指令 // Check Exclude directive
excludeCount := 0 excludeCount := 0
for _, line := range lines { for _, line := range lines {
if strings.HasPrefix(line, "Exclude ") { if strings.HasPrefix(line, "Exclude ") {
excludeCount++ excludeCount++
} }
if excludeCount > 1 { if excludeCount > 1 {
errMsg := "nmap-service-probes文件中只允许有一个Exclude指令" errMsg := "Only one Exclude directive is allowed in nmap-service-probes file"
Common.LogDebug("错误: " + errMsg) Common.LogDebug("Error: " + errMsg)
panic(errMsg) panic(errMsg)
} }
} }
// 验证第一行格式 // Validate first line format
firstLine := lines[0] firstLine := lines[0]
if !(strings.HasPrefix(firstLine, "Exclude ") || strings.HasPrefix(firstLine, "Probe ")) { if !(strings.HasPrefix(firstLine, "Exclude ") || strings.HasPrefix(firstLine, "Probe ")) {
errMsg := "解析错误: 首行必须以\"Probe \"或\"Exclude \"开头" errMsg := "Parsing error: First line must start with \"Probe \" or \"Exclude \""
Common.LogDebug("错误: " + errMsg) Common.LogDebug("Error: " + errMsg)
panic(errMsg) panic(errMsg)
} }
// 处理Exclude指令 // Process Exclude directive
if excludeCount == 1 { if excludeCount == 1 {
v.Exclude = firstLine[len("Exclude")+1:] v.Exclude = firstLine[len("Exclude")+1:]
lines = lines[1:] lines = lines[1:]
Common.LogDebug("解析到Exclude规则: " + v.Exclude) Common.LogDebug("Parsed Exclude rule: " + v.Exclude)
} }
// 合并内容并分割探测器 // Merge content and split probes
content = "\n" + strings.Join(lines, "\n") content = "\n" + strings.Join(lines, "\n")
probeParts := strings.Split(content, "\nProbe")[1:] probeParts := strings.Split(content, "\nProbe")[1:]
// 解析每个探测器 // Parse each probe
for _, probePart := range probeParts { for _, probePart := range probeParts {
probe := Probe{} probe := Probe{}
if err := probe.fromString(probePart); err != nil { if err := probe.fromString(probePart); err != nil {
Common.LogDebug(fmt.Sprintf("解析探测器失败: %v", err)) Common.LogDebug(fmt.Sprintf("Failed to parse probe: %v", err))
continue continue
} }
probes = append(probes, probe) probes = append(probes, probe)
} }
v.AllProbes = probes v.AllProbes = probes
Common.LogDebug(fmt.Sprintf("成功解析 %d 个探测器规则", len(probes))) Common.LogDebug(fmt.Sprintf("Successfully parsed %d probe rules", len(probes)))
} }
// 将探测器转换为名称映射 // Convert probes to name mapping
func (v *VScan) parseProbesToMapKName() { func (v *VScan) parseProbesToMapKName() {
Common.LogDebug("开始构建探测器名称映射") Common.LogDebug("Starting to build probe name mapping")
v.ProbesMapKName = map[string]Probe{} v.ProbesMapKName = map[string]Probe{}
for _, probe := range v.AllProbes { for _, probe := range v.AllProbes {
v.ProbesMapKName[probe.Name] = probe v.ProbesMapKName[probe.Name] = probe
Common.LogDebug("添加探测器映射: " + probe.Name) Common.LogDebug("Added probe mapping: " + probe.Name)
} }
} }
// 设置使用的探测器 // Set probes to be used
func (v *VScan) SetusedProbes() { func (v *VScan) SetusedProbes() {
Common.LogDebug("开始设置要使用的探测器") Common.LogDebug("Starting to set probes to be used")
for _, probe := range v.AllProbes { for _, probe := range v.AllProbes {
if strings.ToLower(probe.Protocol) == "tcp" { if strings.ToLower(probe.Protocol) == "tcp" {
if probe.Name == "SSLSessionReq" { if probe.Name == "SSLSessionReq" {
Common.LogDebug("跳过 SSLSessionReq 探测器") Common.LogDebug("Skipping SSLSessionReq probe")
continue continue
} }
v.Probes = append(v.Probes, probe) v.Probes = append(v.Probes, probe)
Common.LogDebug("添加TCP探测器: " + probe.Name) Common.LogDebug("Added TCP probe: " + probe.Name)
// 特殊处理TLS会话请求 // Special handling for TLS session request
if probe.Name == "TLSSessionReq" { if probe.Name == "TLSSessionReq" {
sslProbe := v.ProbesMapKName["SSLSessionReq"] sslProbe := v.ProbesMapKName["SSLSessionReq"]
v.Probes = append(v.Probes, sslProbe) v.Probes = append(v.Probes, sslProbe)
Common.LogDebug("为TLSSessionReq添加SSL探测器") Common.LogDebug("Added SSL probe for TLSSessionReq")
} }
} else { } else {
v.UdpProbes = append(v.UdpProbes, probe) v.UdpProbes = append(v.UdpProbes, probe)
Common.LogDebug("添加UDP探测器: " + probe.Name) Common.LogDebug("Added UDP probe: " + probe.Name)
} }
} }
Common.LogDebug(fmt.Sprintf("探测器设置完成TCP: %d个, UDP: %d个", Common.LogDebug(fmt.Sprintf("Probe setting completed, TCP: %d, UDP: %d",
len(v.Probes), len(v.UdpProbes))) len(v.Probes), len(v.UdpProbes)))
} }
// 解析match指令获取匹配规则 // Parse match directive to get match rule
func (p *Probe) getMatch(data string) (match Match, err error) { func (p *Probe) getMatch(data string) (match Match, err error) {
Common.LogDebug("开始解析match指令" + data) Common.LogDebug("Starting to parse match directive: " + data)
match = Match{} match = Match{}
// 提取match文本并解析指令语法 // Extract match text and parse directive syntax
matchText := data[len("match")+1:] matchText := data[len("match")+1:]
directive := p.getDirectiveSyntax(matchText) directive := p.getDirectiveSyntax(matchText)
// 分割文本获取pattern和版本信息 // Split text to get pattern and version info
textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter) textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter)
if len(textSplited) == 0 { if len(textSplited) == 0 {
return match, fmt.Errorf("无效的match指令格式") return match, fmt.Errorf("Invalid match directive format")
} }
pattern := textSplited[0] pattern := textSplited[0]
versionInfo := strings.Join(textSplited[1:], "") versionInfo := strings.Join(textSplited[1:], "")
// 解码并编译正则表达式 // Decode and compile regular expression
patternUnescaped, decodeErr := DecodePattern(pattern) patternUnescaped, decodeErr := DecodePattern(pattern)
if decodeErr != nil { if decodeErr != nil {
Common.LogDebug("解码pattern失败: " + decodeErr.Error()) Common.LogDebug("Failed to decode pattern: " + decodeErr.Error())
return match, decodeErr return match, decodeErr
} }
patternUnescapedStr := string([]rune(string(patternUnescaped))) patternUnescapedStr := string([]rune(string(patternUnescaped)))
patternCompiled, compileErr := regexp.Compile(patternUnescapedStr) patternCompiled, compileErr := regexp.Compile(patternUnescapedStr)
if compileErr != nil { if compileErr != nil {
Common.LogDebug("编译正则表达式失败: " + compileErr.Error()) Common.LogDebug("Failed to compile regular expression: " + compileErr.Error())
return match, compileErr return match, compileErr
} }
// 设置match对象属性 // Set match object attributes
match.Service = directive.DirectiveName match.Service = directive.DirectiveName
match.Pattern = pattern match.Pattern = pattern
match.PatternCompiled = patternCompiled match.PatternCompiled = patternCompiled
match.VersionInfo = versionInfo match.VersionInfo = versionInfo
Common.LogDebug(fmt.Sprintf("解析match成功: 服务=%s, Pattern=%s", Common.LogDebug(fmt.Sprintf("Match parsing successful: Service=%s, Pattern=%s",
match.Service, match.Pattern)) match.Service, match.Pattern))
return match, nil return match, nil
} }
// 解析softmatch指令获取软匹配规则 // Parse softmatch directive to get soft match rule
func (p *Probe) getSoftMatch(data string) (softMatch Match, err error) { func (p *Probe) getSoftMatch(data string) (softMatch Match, err error) {
Common.LogDebug("开始解析softmatch指令" + data) Common.LogDebug("Starting to parse softmatch directive: " + data)
softMatch = Match{IsSoft: true} softMatch = Match{IsSoft: true}
// 提取softmatch文本并解析指令语法 // Extract softmatch text and parse directive syntax
matchText := data[len("softmatch")+1:] matchText := data[len("softmatch")+1:]
directive := p.getDirectiveSyntax(matchText) directive := p.getDirectiveSyntax(matchText)
// 分割文本获取pattern和版本信息 // Split text to get pattern and version info
textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter) textSplited := strings.Split(directive.DirectiveStr, directive.Delimiter)
if len(textSplited) == 0 { if len(textSplited) == 0 {
return softMatch, fmt.Errorf("无效的softmatch指令格式") return softMatch, fmt.Errorf("Invalid softmatch directive format")
} }
pattern := textSplited[0] pattern := textSplited[0]
versionInfo := strings.Join(textSplited[1:], "") versionInfo := strings.Join(textSplited[1:], "")
// 解码并编译正则表达式 // Decode and compile regular expression
patternUnescaped, decodeErr := DecodePattern(pattern) patternUnescaped, decodeErr := DecodePattern(pattern)
if decodeErr != nil { if decodeErr != nil {
Common.LogDebug("解码pattern失败: " + decodeErr.Error()) Common.LogDebug("Failed to decode pattern: " + decodeErr.Error())
return softMatch, decodeErr return softMatch, decodeErr
} }
patternUnescapedStr := string([]rune(string(patternUnescaped))) patternUnescapedStr := string([]rune(string(patternUnescaped)))
patternCompiled, compileErr := regexp.Compile(patternUnescapedStr) patternCompiled, compileErr := regexp.Compile(patternUnescapedStr)
if compileErr != nil { if compileErr != nil {
Common.LogDebug("编译正则表达式失败: " + compileErr.Error()) Common.LogDebug("Failed to compile regular expression: " + compileErr.Error())
return softMatch, compileErr return softMatch, compileErr
} }
// 设置softMatch对象属性 // Set softMatch object attributes
softMatch.Service = directive.DirectiveName softMatch.Service = directive.DirectiveName
softMatch.Pattern = pattern softMatch.Pattern = pattern
softMatch.PatternCompiled = patternCompiled softMatch.PatternCompiled = patternCompiled
softMatch.VersionInfo = versionInfo softMatch.VersionInfo = versionInfo
Common.LogDebug(fmt.Sprintf("解析softmatch成功: 服务=%s, Pattern=%s", Common.LogDebug(fmt.Sprintf("Softmatch parsing successful: Service=%s, Pattern=%s",
softMatch.Service, softMatch.Pattern)) softMatch.Service, softMatch.Pattern))
return softMatch, nil return softMatch, nil
} }
// 解码模式字符串,处理转义序列 // Decode pattern string, handle escape sequences
func DecodePattern(s string) ([]byte, error) { func DecodePattern(s string) ([]byte, error) {
Common.LogDebug("开始解码pattern: " + s) Common.LogDebug("Starting to decode pattern: " + s)
sByteOrigin := []byte(s) sByteOrigin := []byte(s)
// 处理十六进制、八进制和结构化转义序列 // Handle hexadecimal, octal, and structured escape sequences
matchRe := regexp.MustCompile(`\\(x[0-9a-fA-F]{2}|[0-7]{1,3}|[aftnrv])`) matchRe := regexp.MustCompile(`\\(x[0-9a-fA-F]{2}|[0-7]{1,3}|[aftnrv])`)
sByteDec := matchRe.ReplaceAllFunc(sByteOrigin, func(match []byte) (v []byte) { sByteDec := matchRe.ReplaceAllFunc(sByteOrigin, func(match []byte) (v []byte) {
var replace []byte var replace []byte
// 处理十六进制转义 // Handle hexadecimal escape
if isHexCode(match) { if isHexCode(match) {
hexNum := match[2:] hexNum := match[2:]
byteNum, _ := strconv.ParseInt(string(hexNum), 16, 32) byteNum, _ := strconv.ParseInt(string(hexNum), 16, 32)
@ -514,20 +514,20 @@ func DecodePattern(s string) ([]byte, error) {
} }
} }
// 处理结构化转义字符 // Handle structured escape characters
if isStructCode(match) { if isStructCode(match) {
structCodeMap := map[int][]byte{ structCodeMap := map[int][]byte{
97: []byte{0x07}, // \a 响铃 97: []byte{0x07}, // \a bell
102: []byte{0x0c}, // \f 换页 102: []byte{0x0c}, // \f form feed
116: []byte{0x09}, // \t 制表符 116: []byte{0x09}, // \t tab
110: []byte{0x0a}, // \n 换行 110: []byte{0x0a}, // \n newline
114: []byte{0x0d}, // \r 回车 114: []byte{0x0d}, // \r carriage return
118: []byte{0x0b}, // \v 垂直制表符 118: []byte{0x0b}, // \v vertical tab
} }
replace = structCodeMap[int(match[1])] replace = structCodeMap[int(match[1])]
} }
// 处理八进制转义 // Handle octal escape
if isOctalCode(match) { if isOctalCode(match) {
octalNum := match[2:] octalNum := match[2:]
byteNum, _ := strconv.ParseInt(string(octalNum), 8, 32) byteNum, _ := strconv.ParseInt(string(octalNum), 8, 32)
@ -536,7 +536,7 @@ func DecodePattern(s string) ([]byte, error) {
return replace return replace
}) })
// 处理其他转义序列 // Handle other escape sequences
matchRe2 := regexp.MustCompile(`\\([^\\])`) matchRe2 := regexp.MustCompile(`\\([^\\])`)
sByteDec2 := matchRe2.ReplaceAllFunc(sByteDec, func(match []byte) (v []byte) { sByteDec2 := matchRe2.ReplaceAllFunc(sByteDec, func(match []byte) (v []byte) {
if isOtherEscapeCode(match) { if isOtherEscapeCode(match) {
@ -545,57 +545,57 @@ func DecodePattern(s string) ([]byte, error) {
return match return match
}) })
Common.LogDebug("pattern解码完成") Common.LogDebug("Pattern decoding completed")
return sByteDec2, nil return sByteDec2, nil
} }
// ProbesRarity 用于按稀有度排序的探测器切片 // ProbesRarity is a slice of probes for sorting by rarity
type ProbesRarity []Probe type ProbesRarity []Probe
// Len 返回切片长度,实现 sort.Interface 接口 // Len returns slice length, implements sort.Interface
func (ps ProbesRarity) Len() int { func (ps ProbesRarity) Len() int {
return len(ps) return len(ps)
} }
// Swap 交换切片中的两个元素,实现 sort.Interface 接口 // Swap exchanges two elements in the slice, implements sort.Interface
func (ps ProbesRarity) Swap(i, j int) { func (ps ProbesRarity) Swap(i, j int) {
ps[i], ps[j] = ps[j], ps[i] ps[i], ps[j] = ps[j], ps[i]
} }
// Less 比较函数,按稀有度升序排序,实现 sort.Interface 接口 // Less comparison function, sorts by rarity in ascending order, implements sort.Interface
func (ps ProbesRarity) Less(i, j int) bool { func (ps ProbesRarity) Less(i, j int) bool {
return ps[i].Rarity < ps[j].Rarity return ps[i].Rarity < ps[j].Rarity
} }
// Target 定义目标结构体 // Target defines target structure
type Target struct { type Target struct {
IP string // 目标IP地址 IP string // Target IP address
Port int // 目标端口 Port int // Target port
Protocol string // 协议类型 Protocol string // Protocol type
} }
// ContainsPort 检查指定端口是否在探测器的端口范围内 // ContainsPort checks if the specified port is within the probe's port range
func (p *Probe) ContainsPort(testPort int) bool { func (p *Probe) ContainsPort(testPort int) bool {
Common.LogDebug(fmt.Sprintf("检查端口 %d 是否在探测器端口范围内: %s", testPort, p.Ports)) Common.LogDebug(fmt.Sprintf("Checking if port %d is within probe port range: %s", testPort, p.Ports))
// 检查单个端口 // Check individual ports
ports := strings.Split(p.Ports, ",") ports := strings.Split(p.Ports, ",")
for _, port := range ports { for _, port := range ports {
port = strings.TrimSpace(port) port = strings.TrimSpace(port)
cmpPort, err := strconv.Atoi(port) cmpPort, err := strconv.Atoi(port)
if err == nil && testPort == cmpPort { if err == nil && testPort == cmpPort {
Common.LogDebug(fmt.Sprintf("端口 %d 匹配单个端口", testPort)) Common.LogDebug(fmt.Sprintf("Port %d matches individual port", testPort))
return true return true
} }
} }
// 检查端口范围 // Check port ranges
for _, port := range ports { for _, port := range ports {
port = strings.TrimSpace(port) port = strings.TrimSpace(port)
if strings.Contains(port, "-") { if strings.Contains(port, "-") {
portRange := strings.Split(port, "-") portRange := strings.Split(port, "-")
if len(portRange) != 2 { if len(portRange) != 2 {
Common.LogDebug("无效的端口范围格式: " + port) Common.LogDebug("Invalid port range format: " + port)
continue continue
} }
@ -603,62 +603,62 @@ func (p *Probe) ContainsPort(testPort int) bool {
end, err2 := strconv.Atoi(strings.TrimSpace(portRange[1])) end, err2 := strconv.Atoi(strings.TrimSpace(portRange[1]))
if err1 != nil || err2 != nil { if err1 != nil || err2 != nil {
Common.LogDebug(fmt.Sprintf("解析端口范围失败: %s", port)) Common.LogDebug(fmt.Sprintf("Failed to parse port range: %s", port))
continue continue
} }
if testPort >= start && testPort <= end { if testPort >= start && testPort <= end {
Common.LogDebug(fmt.Sprintf("端口 %d 在范围 %d-%d 内", testPort, start, end)) Common.LogDebug(fmt.Sprintf("Port %d is within range %d-%d", testPort, start, end))
return true return true
} }
} }
} }
Common.LogDebug(fmt.Sprintf("端口 %d 不在探测器端口范围内", testPort)) Common.LogDebug(fmt.Sprintf("Port %d is not within probe port range", testPort))
return false return false
} }
// MatchPattern 使用正则表达式匹配响应内容 // MatchPattern uses regular expression to match response content
func (m *Match) MatchPattern(response []byte) bool { func (m *Match) MatchPattern(response []byte) bool {
// 将响应转换为字符串并进行匹配 // Convert response to string and match
responseStr := string([]rune(string(response))) responseStr := string([]rune(string(response)))
foundItems := m.PatternCompiled.FindStringSubmatch(responseStr) foundItems := m.PatternCompiled.FindStringSubmatch(responseStr)
if len(foundItems) > 0 { if len(foundItems) > 0 {
m.FoundItems = foundItems m.FoundItems = foundItems
Common.LogDebug(fmt.Sprintf("匹配成功,找到 %d 个匹配项", len(foundItems))) Common.LogDebug(fmt.Sprintf("Match successful, found %d matching items", len(foundItems)))
return true return true
} }
return false return false
} }
// ParseVersionInfo 解析版本信息并返回额外信息结构 // ParseVersionInfo parses version information and returns extra information structure
func (m *Match) ParseVersionInfo(response []byte) Extras { func (m *Match) ParseVersionInfo(response []byte) Extras {
Common.LogDebug("开始解析版本信息") Common.LogDebug("Starting to parse version information")
var extras = Extras{} var extras = Extras{}
// 替换版本信息中的占位符 // Replace placeholders in version info
foundItems := m.FoundItems[1:] // 跳过第一个完整匹配项 foundItems := m.FoundItems[1:] // Skip the first complete match item
versionInfo := m.VersionInfo versionInfo := m.VersionInfo
for index, value := range foundItems { for index, value := range foundItems {
dollarName := "$" + strconv.Itoa(index+1) dollarName := "$" + strconv.Itoa(index+1)
versionInfo = strings.Replace(versionInfo, dollarName, value, -1) versionInfo = strings.Replace(versionInfo, dollarName, value, -1)
} }
Common.LogDebug("替换后的版本信息: " + versionInfo) Common.LogDebug("Version info after replacement: " + versionInfo)
// 定义解析函数 // Define parsing function
parseField := func(field, pattern string) string { parseField := func(field, pattern string) string {
patterns := []string{ patterns := []string{
pattern + `/([^/]*)/`, // 斜线分隔 pattern + `/([^/]*)/`, // Slash delimiter
pattern + `\|([^|]*)\|`, // 竖线分隔 pattern + `\|([^|]*)\|`, // Pipe delimiter
} }
for _, p := range patterns { for _, p := range patterns {
if strings.Contains(versionInfo, pattern) { if strings.Contains(versionInfo, pattern) {
regex := regexp.MustCompile(p) regex := regexp.MustCompile(p)
if matches := regex.FindStringSubmatch(versionInfo); len(matches) > 1 { if matches := regex.FindStringSubmatch(versionInfo); len(matches) > 1 {
Common.LogDebug(fmt.Sprintf("解析到%s: %s", field, matches[1])) Common.LogDebug(fmt.Sprintf("Parsed %s: %s", field, matches[1]))
return matches[1] return matches[1]
} }
} }
@ -666,15 +666,15 @@ func (m *Match) ParseVersionInfo(response []byte) Extras {
return "" return ""
} }
// 解析各个字段 // Parse each field
extras.VendorProduct = parseField("厂商产品", " p") extras.VendorProduct = parseField("vendor product", " p")
extras.Version = parseField("版本", " v") extras.Version = parseField("version", " v")
extras.Info = parseField("信息", " i") extras.Info = parseField("info", " i")
extras.Hostname = parseField("主机名", " h") extras.Hostname = parseField("hostname", " h")
extras.OperatingSystem = parseField("操作系统", " o") extras.OperatingSystem = parseField("operating system", " o")
extras.DeviceType = parseField("设备类型", " d") extras.DeviceType = parseField("device type", " d")
// 特殊处理CPE // Special handling for CPE
if strings.Contains(versionInfo, " cpe:/") || strings.Contains(versionInfo, " cpe:|") { if strings.Contains(versionInfo, " cpe:/") || strings.Contains(versionInfo, " cpe:|") {
cpePatterns := []string{`cpe:/([^/]*)`, `cpe:\|([^|]*)`} cpePatterns := []string{`cpe:/([^/]*)`, `cpe:\|([^|]*)`}
for _, pattern := range cpePatterns { for _, pattern := range cpePatterns {
@ -685,7 +685,7 @@ func (m *Match) ParseVersionInfo(response []byte) Extras {
} else { } else {
extras.CPE = cpeName[0] extras.CPE = cpeName[0]
} }
Common.LogDebug("解析到CPE: " + extras.CPE) Common.LogDebug("Parsed CPE: " + extras.CPE)
break break
} }
} }
@ -694,12 +694,12 @@ func (m *Match) ParseVersionInfo(response []byte) Extras {
return extras return extras
} }
// ToMap 将 Extras 转换为 map[string]string // ToMap converts Extras to map[string]string
func (e *Extras) ToMap() map[string]string { func (e *Extras) ToMap() map[string]string {
Common.LogDebug("开始转换Extras为Map") Common.LogDebug("Starting to convert Extras to Map")
result := make(map[string]string) result := make(map[string]string)
// 定义字段映射 // Define field mapping
fields := map[string]string{ fields := map[string]string{
"vendor_product": e.VendorProduct, "vendor_product": e.VendorProduct,
"version": e.Version, "version": e.Version,
@ -710,31 +710,31 @@ func (e *Extras) ToMap() map[string]string {
"cpe": e.CPE, "cpe": e.CPE,
} }
// 添加非空字段到结果map // Add non-empty fields to result map
for key, value := range fields { for key, value := range fields {
if value != "" { if value != "" {
result[key] = value result[key] = value
Common.LogDebug(fmt.Sprintf("添加字段 %s: %s", key, value)) Common.LogDebug(fmt.Sprintf("Added field %s: %s", key, value))
} }
} }
Common.LogDebug(fmt.Sprintf("转换完成,共有 %d 个字段", len(result))) Common.LogDebug(fmt.Sprintf("Conversion completed, total %d fields", len(result)))
return result return result
} }
func DecodeData(s string) ([]byte, error) { func DecodeData(s string) ([]byte, error) {
if len(s) == 0 { if len(s) == 0 {
Common.LogDebug("输入数据为空") Common.LogDebug("Input data is empty")
return nil, fmt.Errorf("empty input") return nil, fmt.Errorf("empty input")
} }
Common.LogDebug(fmt.Sprintf("开始解码数据,长度: %d, 内容: %q", len(s), s)) Common.LogDebug(fmt.Sprintf("Starting to decode data, length: %d, content: %q", len(s), s))
sByteOrigin := []byte(s) sByteOrigin := []byte(s)
// 处理十六进制、八进制和结构化转义序列 // Handle hexadecimal, octal, and structured escape sequences
matchRe := regexp.MustCompile(`\\(x[0-9a-fA-F]{2}|[0-7]{1,3}|[aftnrv])`) matchRe := regexp.MustCompile(`\\(x[0-9a-fA-F]{2}|[0-7]{1,3}|[aftnrv])`)
sByteDec := matchRe.ReplaceAllFunc(sByteOrigin, func(match []byte) []byte { sByteDec := matchRe.ReplaceAllFunc(sByteOrigin, func(match []byte) []byte {
// 处理十六进制转义 // Handle hexadecimal escape
if isHexCode(match) { if isHexCode(match) {
hexNum := match[2:] hexNum := match[2:]
byteNum, err := strconv.ParseInt(string(hexNum), 16, 32) byteNum, err := strconv.ParseInt(string(hexNum), 16, 32)
@ -744,15 +744,15 @@ func DecodeData(s string) ([]byte, error) {
return []byte{uint8(byteNum)} return []byte{uint8(byteNum)}
} }
// 处理结构化转义字符 // Handle structured escape characters
if isStructCode(match) { if isStructCode(match) {
structCodeMap := map[int][]byte{ structCodeMap := map[int][]byte{
97: []byte{0x07}, // \a 响铃 97: []byte{0x07}, // \a bell
102: []byte{0x0c}, // \f 换页 102: []byte{0x0c}, // \f form feed
116: []byte{0x09}, // \t 制表符 116: []byte{0x09}, // \t tab
110: []byte{0x0a}, // \n 换行 110: []byte{0x0a}, // \n newline
114: []byte{0x0d}, // \r 回车 114: []byte{0x0d}, // \r carriage return
118: []byte{0x0b}, // \v 垂直制表符 118: []byte{0x0b}, // \v vertical tab
} }
if replace, ok := structCodeMap[int(match[1])]; ok { if replace, ok := structCodeMap[int(match[1])]; ok {
return replace return replace
@ -760,7 +760,7 @@ func DecodeData(s string) ([]byte, error) {
return match return match
} }
// 处理八进制转义 // Handle octal escape
if isOctalCode(match) { if isOctalCode(match) {
octalNum := match[2:] octalNum := match[2:]
byteNum, err := strconv.ParseInt(string(octalNum), 8, 32) byteNum, err := strconv.ParseInt(string(octalNum), 8, 32)
@ -770,11 +770,11 @@ func DecodeData(s string) ([]byte, error) {
return []byte{uint8(byteNum)} return []byte{uint8(byteNum)}
} }
Common.LogDebug(fmt.Sprintf("无法识别的转义序列: %s", string(match))) Common.LogDebug(fmt.Sprintf("Unrecognized escape sequence: %s", string(match)))
return match return match
}) })
// 处理其他转义序列 // Handle other escape sequences
matchRe2 := regexp.MustCompile(`\\([^\\])`) matchRe2 := regexp.MustCompile(`\\([^\\])`)
sByteDec2 := matchRe2.ReplaceAllFunc(sByteDec, func(match []byte) []byte { sByteDec2 := matchRe2.ReplaceAllFunc(sByteDec, func(match []byte) []byte {
if len(match) < 2 { if len(match) < 2 {
@ -787,39 +787,39 @@ func DecodeData(s string) ([]byte, error) {
}) })
if len(sByteDec2) == 0 { if len(sByteDec2) == 0 {
Common.LogDebug("解码后数据为空") Common.LogDebug("Decoded data is empty")
return nil, fmt.Errorf("decoded data is empty") return nil, fmt.Errorf("decoded data is empty")
} }
Common.LogDebug(fmt.Sprintf("解码完成,结果长度: %d, 内容: %x", len(sByteDec2), sByteDec2)) Common.LogDebug(fmt.Sprintf("Decoding completed, result length: %d, content: %x", len(sByteDec2), sByteDec2))
return sByteDec2, nil return sByteDec2, nil
} }
// GetAddress 获取目标的完整地址IP:端口) // GetAddress gets the target's full address (IP:port)
func (t *Target) GetAddress() string { func (t *Target) GetAddress() string {
addr := t.IP + ":" + strconv.Itoa(t.Port) addr := t.IP + ":" + strconv.Itoa(t.Port)
Common.LogDebug("获取目标地址: " + addr) Common.LogDebug("Getting target address: " + addr)
return addr return addr
} }
// trimBanner 处理和清理横幅数据 // trimBanner processes and cleans banner data
func trimBanner(buf []byte) string { func trimBanner(buf []byte) string {
Common.LogDebug("开始处理横幅数据") Common.LogDebug("Starting to process banner data")
bufStr := string(buf) bufStr := string(buf)
// 特殊处理SMB协议 // Special handling for SMB protocol
if strings.Contains(bufStr, "SMB") { if strings.Contains(bufStr, "SMB") {
banner := hex.EncodeToString(buf) banner := hex.EncodeToString(buf)
if len(banner) > 0xa+6 && banner[0xa:0xa+6] == "534d42" { // "SMB" in hex if len(banner) > 0xa+6 && banner[0xa:0xa+6] == "534d42" { // "SMB" in hex
Common.LogDebug("检测到SMB协议数据") Common.LogDebug("Detected SMB protocol data")
plain := banner[0xa2:] plain := banner[0xa2:]
data, err := hex.DecodeString(plain) data, err := hex.DecodeString(plain)
if err != nil { if err != nil {
Common.LogDebug("SMB数据解码失败: " + err.Error()) Common.LogDebug("Failed to decode SMB data: " + err.Error())
return bufStr return bufStr
} }
// 解析domain // Parse domain
var domain string var domain string
var index int var index int
for i, s := range data { for i, s := range data {
@ -831,7 +831,7 @@ func trimBanner(buf []byte) string {
} }
} }
// 解析hostname // Parse hostname
var hostname string var hostname string
remainData := data[index:] remainData := data[index:]
for i, h := range remainData { for i, h := range remainData {
@ -844,12 +844,12 @@ func trimBanner(buf []byte) string {
} }
smbBanner := fmt.Sprintf("hostname: %s domain: %s", hostname, domain) smbBanner := fmt.Sprintf("hostname: %s domain: %s", hostname, domain)
Common.LogDebug("SMB横幅: " + smbBanner) Common.LogDebug("SMB banner: " + smbBanner)
return smbBanner return smbBanner
} }
} }
// 处理常规数据 // Process regular data
var src string var src string
for _, ch := range bufStr { for _, ch := range bufStr {
if ch > 32 && ch < 125 { if ch > 32 && ch < 125 {
@ -859,19 +859,19 @@ func trimBanner(buf []byte) string {
} }
} }
// 清理多余空白 // Clean up extra whitespace
re := regexp.MustCompile(`\s{2,}`) re := regexp.MustCompile(`\s{2,}`)
src = re.ReplaceAllString(src, ".") src = re.ReplaceAllString(src, ".")
result := strings.TrimSpace(src) result := strings.TrimSpace(src)
Common.LogDebug("处理后的横幅: " + result) Common.LogDebug("Processed banner: " + result)
return result return result
} }
// Init 初始化VScan对象 // Init initializes the VScan object
func (v *VScan) Init() { func (v *VScan) Init() {
Common.LogDebug("开始初始化VScan") Common.LogDebug("Starting to initialize VScan")
v.parseProbesFromContent(ProbeString) v.parseProbesFromContent(ProbeString)
v.parseProbesToMapKName() v.parseProbesToMapKName()
v.SetusedProbes() v.SetusedProbes()
Common.LogDebug("VScan初始化完成") Common.LogDebug("VScan initialization completed")
} }

View File

@ -9,54 +9,54 @@ import (
"time" "time"
) )
// ServiceInfo 定义服务识别的结果信息 // ServiceInfo defines the service identification result information
type ServiceInfo struct { type ServiceInfo struct {
Name string // 服务名称,如 http、ssh 等 Name string // Service name, such as http, ssh, etc.
Banner string // 服务返回的横幅信息 Banner string // Banner information returned by the service
Version string // 服务版本号 Version string // Service version number
Extras map[string]string // 其他额外信息,如操作系统、产品名等 Extras map[string]string // Other additional information, such as operating system, product name, etc.
} }
// Result 定义单次探测的结果 // Result defines the result of a single detection
type Result struct { type Result struct {
Service Service // 识别出的服务信息 Service Service // Identified service information
Banner string // 服务横幅 Banner string // Service banner
Extras map[string]string // 额外信息 Extras map[string]string // Additional information
Send []byte // 发送的探测数据 Send []byte // Probe data sent
Recv []byte // 接收到的响应数据 Recv []byte // Response data received
} }
// Service 定义服务的基本信息 // Service defines the basic information of a service
type Service struct { type Service struct {
Name string // 服务名称 Name string // Service name
Extras map[string]string // 服务的额外属性 Extras map[string]string // Additional service attributes
} }
// Info 定义单个端口探测的上下文信息 // Info defines the context information for a single port probe
type Info struct { type Info struct {
Address string // 目标IP地址 Address string // Target IP address
Port int // 目标端口 Port int // Target port
Conn net.Conn // 网络连接 Conn net.Conn // Network connection
Result Result // 探测结果 Result Result // Detection result
Found bool // 是否成功识别服务 Found bool // Whether the service was successfully identified
} }
// PortInfoScanner 定义端口服务识别器 // PortInfoScanner defines a port service identifier
type PortInfoScanner struct { type PortInfoScanner struct {
Address string // 目标IP地址 Address string // Target IP address
Port int // 目标端口 Port int // Target port
Conn net.Conn // 网络连接 Conn net.Conn // Network connection
Timeout time.Duration // 超时时间 Timeout time.Duration // Timeout duration
info *Info // 探测上下文 info *Info // Detection context
} }
// 预定义的基础探测器 // Predefined basic probes
var ( var (
null = new(Probe) // 空探测器,用于基本协议识别 null = new(Probe) // Empty probe, used for basic protocol identification
common = new(Probe) // 通用探测器,用于常见服务识别 common = new(Probe) // Common probe, used for common service identification
) )
// NewPortInfoScanner 创建新的端口服务识别器实例 // NewPortInfoScanner creates a new port service identifier instance
func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration) *PortInfoScanner { func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration) *PortInfoScanner {
return &PortInfoScanner{ return &PortInfoScanner{
Address: addr, Address: addr,
@ -74,12 +74,12 @@ func NewPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Durat
} }
} }
// Identify 执行服务识别,返回识别结果 // Identify performs service identification and returns the result
func (s *PortInfoScanner) Identify() (*ServiceInfo, error) { func (s *PortInfoScanner) Identify() (*ServiceInfo, error) {
Common.LogDebug(fmt.Sprintf("开始识别服务 %s:%d", s.Address, s.Port)) Common.LogDebug(fmt.Sprintf("Starting to identify service %s:%d", s.Address, s.Port))
s.info.PortInfo() s.info.PortInfo()
// 构造返回结果 // Construct the return result
serviceInfo := &ServiceInfo{ serviceInfo := &ServiceInfo{
Name: s.info.Result.Service.Name, Name: s.info.Result.Service.Name,
Banner: s.info.Result.Banner, Banner: s.info.Result.Banner,
@ -87,104 +87,104 @@ func (s *PortInfoScanner) Identify() (*ServiceInfo, error) {
Extras: make(map[string]string), Extras: make(map[string]string),
} }
// 复制额外信息 // Copy additional information
for k, v := range s.info.Result.Service.Extras { for k, v := range s.info.Result.Service.Extras {
serviceInfo.Extras[k] = v serviceInfo.Extras[k] = v
} }
Common.LogDebug(fmt.Sprintf("服务识别完成 %s:%d => %s", s.Address, s.Port, serviceInfo.Name)) Common.LogDebug(fmt.Sprintf("Service identification completed %s:%d => %s", s.Address, s.Port, serviceInfo.Name))
return serviceInfo, nil return serviceInfo, nil
} }
// PortInfo 执行端口服务识别的主要逻辑 // PortInfo executes the main logic of port service identification
func (i *Info) PortInfo() { func (i *Info) PortInfo() {
// 1. 首先尝试读取服务的初始响应 // 1. First try to read the initial response from the service
if response, err := i.Read(); err == nil && len(response) > 0 { if response, err := i.Read(); err == nil && len(response) > 0 {
Common.LogDebug(fmt.Sprintf("收到初始响应: %d 字节", len(response))) Common.LogDebug(fmt.Sprintf("Received initial response: %d bytes", len(response)))
// 使用基础探测器检查响应 // Check the response using basic probes
Common.LogDebug("尝试使用基础探测器(null/common)检查响应") Common.LogDebug("Attempting to check response using basic probes (null/common)")
if i.tryProbes(response, []*Probe{null, common}) { if i.tryProbes(response, []*Probe{null, common}) {
Common.LogDebug("基础探测器匹配成功") Common.LogDebug("Basic probe matching successful")
return return
} }
Common.LogDebug("基础探测器未匹配") Common.LogDebug("Basic probes did not match")
} else if err != nil { } else if err != nil {
Common.LogDebug(fmt.Sprintf("读取初始响应失败: %v", err)) Common.LogDebug(fmt.Sprintf("Failed to read initial response: %v", err))
} }
// 记录已使用的探测器,避免重复使用 // Record used probes to avoid duplication
usedProbes := make(map[string]struct{}) usedProbes := make(map[string]struct{})
// 2. 尝试使用端口专用探测器 // 2. Try to use port-specific probes
Common.LogDebug(fmt.Sprintf("尝试使用端口 %d 的专用探测器", i.Port)) Common.LogDebug(fmt.Sprintf("Attempting to use dedicated probes for port %d", i.Port))
if i.processPortMapProbes(usedProbes) { if i.processPortMapProbes(usedProbes) {
Common.LogDebug("端口专用探测器匹配成功") Common.LogDebug("Port-specific probe matching successful")
return return
} }
Common.LogDebug("端口专用探测器未匹配") Common.LogDebug("Port-specific probes did not match")
// 3. 使用默认探测器列表 // 3. Use the default probe list
Common.LogDebug("尝试使用默认探测器列表") Common.LogDebug("Attempting to use default probe list")
if i.processDefaultProbes(usedProbes) { if i.processDefaultProbes(usedProbes) {
Common.LogDebug("默认探测器匹配成功") Common.LogDebug("Default probe matching successful")
return return
} }
Common.LogDebug("默认探测器未匹配") Common.LogDebug("Default probes did not match")
// 4. 如果所有探测都失败,标记为未知服务 // 4. If all probes fail, mark as unknown service
if strings.TrimSpace(i.Result.Service.Name) == "" { if strings.TrimSpace(i.Result.Service.Name) == "" {
Common.LogDebug("未识别出服务,标记为 unknown") Common.LogDebug("Service not recognized, marking as unknown")
i.Result.Service.Name = "unknown" i.Result.Service.Name = "unknown"
} }
} }
// tryProbes 尝试使用指定的探测器列表检查响应 // tryProbes attempts to use the specified probe list to check the response
func (i *Info) tryProbes(response []byte, probes []*Probe) bool { func (i *Info) tryProbes(response []byte, probes []*Probe) bool {
for _, probe := range probes { for _, probe := range probes {
Common.LogDebug(fmt.Sprintf("尝试探测器: %s", probe.Name)) Common.LogDebug(fmt.Sprintf("Attempting probe: %s", probe.Name))
i.GetInfo(response, probe) i.GetInfo(response, probe)
if i.Found { if i.Found {
Common.LogDebug(fmt.Sprintf("探测器 %s 匹配成功", probe.Name)) Common.LogDebug(fmt.Sprintf("Probe %s matched successfully", probe.Name))
return true return true
} }
} }
return false return false
} }
// processPortMapProbes 处理端口映射中的专用探测器 // processPortMapProbes processes dedicated probes in the port mapping
func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool { func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
// 检查是否存在端口专用探测器 // Check if port-specific probes exist
if len(Common.PortMap[i.Port]) == 0 { if len(Common.PortMap[i.Port]) == 0 {
Common.LogDebug(fmt.Sprintf("端口 %d 没有专用探测器", i.Port)) Common.LogDebug(fmt.Sprintf("Port %d has no dedicated probes", i.Port))
return false return false
} }
// 遍历端口专用探测器 // Iterate through port-specific probes
for _, name := range Common.PortMap[i.Port] { for _, name := range Common.PortMap[i.Port] {
Common.LogDebug(fmt.Sprintf("尝试端口专用探测器: %s", name)) Common.LogDebug(fmt.Sprintf("Attempting port-specific probe: %s", name))
usedProbes[name] = struct{}{} usedProbes[name] = struct{}{}
probe := v.ProbesMapKName[name] probe := v.ProbesMapKName[name]
// 解码探测数据 // Decode probe data
probeData, err := DecodeData(probe.Data) probeData, err := DecodeData(probe.Data)
if err != nil || len(probeData) == 0 { if err != nil || len(probeData) == 0 {
Common.LogDebug(fmt.Sprintf("探测器 %s 数据解码失败", name)) Common.LogDebug(fmt.Sprintf("Failed to decode probe data for %s", name))
continue continue
} }
// 发送探测数据并获取响应 // Send probe data and get response
Common.LogDebug(fmt.Sprintf("发送探测数据: %d 字节", len(probeData))) Common.LogDebug(fmt.Sprintf("Sending probe data: %d bytes", len(probeData)))
if response := i.Connect(probeData); len(response) > 0 { if response := i.Connect(probeData); len(response) > 0 {
Common.LogDebug(fmt.Sprintf("收到响应: %d 字节", len(response))) Common.LogDebug(fmt.Sprintf("Received response: %d bytes", len(response)))
// 使用当前探测器检查响应 // Check response with current probe
i.GetInfo(response, &probe) i.GetInfo(response, &probe)
if i.Found { if i.Found {
return true return true
} }
// 根据探测器类型进行额外检查 // Perform additional checks based on probe type
switch name { switch name {
case "GenericLines": case "GenericLines":
if i.tryProbes(response, []*Probe{null}) { if i.tryProbes(response, []*Probe{null}) {
@ -202,14 +202,14 @@ func (i *Info) processPortMapProbes(usedProbes map[string]struct{}) bool {
return false return false
} }
// processDefaultProbes 处理默认探测器列表 // processDefaultProbes processes the default probe list
func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool { func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
failCount := 0 failCount := 0
const maxFailures = 10 // 最大失败次数 const maxFailures = 10 // Maximum failure count
// 遍历默认探测器列表 // Iterate through the default probe list
for _, name := range Common.DefaultMap { for _, name := range Common.DefaultMap {
// 跳过已使用的探测器 // Skip already used probes
if _, used := usedProbes[name]; used { if _, used := usedProbes[name]; used {
continue continue
} }
@ -220,7 +220,7 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
continue continue
} }
// 发送探测数据并获取响应 // Send probe data and get response
response := i.Connect(probeData) response := i.Connect(probeData)
if len(response) == 0 { if len(response) == 0 {
failCount++ failCount++
@ -230,13 +230,13 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
continue continue
} }
// 使用当前探测器检查响应 // Check response with current probe
i.GetInfo(response, &probe) i.GetInfo(response, &probe)
if i.Found { if i.Found {
return true return true
} }
// 根据探测器类型进行额外检查 // Perform additional checks based on probe type
switch name { switch name {
case "GenericLines": case "GenericLines":
if i.tryProbes(response, []*Probe{null}) { if i.tryProbes(response, []*Probe{null}) {
@ -250,7 +250,7 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
} }
} }
// 尝试使用端口映射中的其他探测器 // Try to use other probes in the port mapping
if len(Common.PortMap[i.Port]) > 0 { if len(Common.PortMap[i.Port]) > 0 {
for _, mappedName := range Common.PortMap[i.Port] { for _, mappedName := range Common.PortMap[i.Port] {
usedProbes[mappedName] = struct{}{} usedProbes[mappedName] = struct{}{}
@ -265,13 +265,13 @@ func (i *Info) processDefaultProbes(usedProbes map[string]struct{}) bool {
return false return false
} }
// GetInfo 分析响应数据并提取服务信息 // GetInfo analyzes response data and extracts service information
func (i *Info) GetInfo(response []byte, probe *Probe) { func (i *Info) GetInfo(response []byte, probe *Probe) {
Common.LogDebug(fmt.Sprintf("开始分析响应数据,长度: %d", len(response))) Common.LogDebug(fmt.Sprintf("Starting to analyze response data, length: %d", len(response)))
// 响应数据有效性检查 // Check response data validity
if len(response) <= 0 { if len(response) <= 0 {
Common.LogDebug("响应数据为空") Common.LogDebug("Response data is empty")
return return
} }
@ -281,42 +281,42 @@ func (i *Info) GetInfo(response []byte, probe *Probe) {
softFound bool softFound bool
) )
// 处理主要匹配规则 // Process main matching rules
Common.LogDebug(fmt.Sprintf("处理探测器 %s 的主要匹配规则", probe.Name)) Common.LogDebug(fmt.Sprintf("Processing main matching rules for probe %s", probe.Name))
if matched, match := i.processMatches(response, probe.Matchs); matched { if matched, match := i.processMatches(response, probe.Matchs); matched {
Common.LogDebug("找到硬匹配") Common.LogDebug("Hard match found")
return return
} else if match != nil { } else if match != nil {
Common.LogDebug("找到软匹配") Common.LogDebug("Soft match found")
softFound = true softFound = true
softMatch = *match softMatch = *match
} }
// 处理回退匹配规则 // Process fallback matching rules
if probe.Fallback != "" { if probe.Fallback != "" {
Common.LogDebug(fmt.Sprintf("尝试回退匹配: %s", probe.Fallback)) Common.LogDebug(fmt.Sprintf("Attempting fallback match: %s", probe.Fallback))
if fbProbe, ok := v.ProbesMapKName[probe.Fallback]; ok { if fbProbe, ok := v.ProbesMapKName[probe.Fallback]; ok {
if matched, match := i.processMatches(response, fbProbe.Matchs); matched { if matched, match := i.processMatches(response, fbProbe.Matchs); matched {
Common.LogDebug("回退匹配成功") Common.LogDebug("Fallback match successful")
return return
} else if match != nil { } else if match != nil {
Common.LogDebug("找到回退软匹配") Common.LogDebug("Fallback soft match found")
softFound = true softFound = true
softMatch = *match softMatch = *match
} }
} }
} }
// 处理未找到匹配的情况 // Handle case when no match is found
if !i.Found { if !i.Found {
Common.LogDebug("未找到硬匹配,处理未匹配情况") Common.LogDebug("No hard match found, handling no match case")
i.handleNoMatch(response, result, softFound, softMatch) i.handleNoMatch(response, result, softFound, softMatch)
} }
} }
// processMatches 处理匹配规则集 // processMatches processes the set of matching rules
func (i *Info) processMatches(response []byte, matches *[]Match) (bool, *Match) { func (i *Info) processMatches(response []byte, matches *[]Match) (bool, *Match) {
Common.LogDebug(fmt.Sprintf("开始处理匹配规则,共 %d 条", len(*matches))) Common.LogDebug(fmt.Sprintf("Starting to process matching rules, total %d rules", len(*matches)))
var softMatch *Match var softMatch *Match
for _, match := range *matches { for _, match := range *matches {
@ -325,11 +325,11 @@ func (i *Info) processMatches(response []byte, matches *[]Match) (bool, *Match)
} }
if !match.IsSoft { if !match.IsSoft {
Common.LogDebug(fmt.Sprintf("找到硬匹配: %s", match.Service)) Common.LogDebug(fmt.Sprintf("Hard match found: %s", match.Service))
i.handleHardMatch(response, &match) i.handleHardMatch(response, &match)
return true, nil return true, nil
} else if softMatch == nil { } else if softMatch == nil {
Common.LogDebug(fmt.Sprintf("找到软匹配: %s", match.Service)) Common.LogDebug(fmt.Sprintf("Soft match found: %s", match.Service))
tmpMatch := match tmpMatch := match
softMatch = &tmpMatch softMatch = &tmpMatch
} }
@ -338,9 +338,9 @@ func (i *Info) processMatches(response []byte, matches *[]Match) (bool, *Match)
return false, softMatch return false, softMatch
} }
// handleHardMatch 处理硬匹配结果 // handleHardMatch handles hard match results
func (i *Info) handleHardMatch(response []byte, match *Match) { func (i *Info) handleHardMatch(response []byte, match *Match) {
Common.LogDebug(fmt.Sprintf("处理硬匹配结果: %s", match.Service)) Common.LogDebug(fmt.Sprintf("Processing hard match result: %s", match.Service))
result := &i.Result result := &i.Result
extras := match.ParseVersionInfo(response) extras := match.ParseVersionInfo(response)
extrasMap := extras.ToMap() extrasMap := extras.ToMap()
@ -350,64 +350,64 @@ func (i *Info) handleHardMatch(response []byte, match *Match) {
result.Banner = trimBanner(response) result.Banner = trimBanner(response)
result.Service.Extras = extrasMap result.Service.Extras = extrasMap
// 特殊处理 microsoft-ds 服务 // Special handling for microsoft-ds service
if result.Service.Name == "microsoft-ds" { if result.Service.Name == "microsoft-ds" {
Common.LogDebug("特殊处理 microsoft-ds 服务") Common.LogDebug("Special handling for microsoft-ds service")
result.Service.Extras["hostname"] = result.Banner result.Service.Extras["hostname"] = result.Banner
} }
i.Found = true i.Found = true
Common.LogDebug(fmt.Sprintf("服务识别结果: %s, Banner: %s", result.Service.Name, result.Banner)) Common.LogDebug(fmt.Sprintf("Service identification result: %s, Banner: %s", result.Service.Name, result.Banner))
} }
// handleNoMatch 处理未找到匹配的情况 // handleNoMatch handles the case when no match is found
func (i *Info) handleNoMatch(response []byte, result *Result, softFound bool, softMatch Match) { func (i *Info) handleNoMatch(response []byte, result *Result, softFound bool, softMatch Match) {
Common.LogDebug("处理未匹配情况") Common.LogDebug("Handling no match case")
result.Banner = trimBanner(response) result.Banner = trimBanner(response)
if !softFound { if !softFound {
// 尝试识别 HTTP 服务 // Try to identify HTTP service
if strings.Contains(result.Banner, "HTTP/") || if strings.Contains(result.Banner, "HTTP/") ||
strings.Contains(result.Banner, "html") { strings.Contains(result.Banner, "html") {
Common.LogDebug("识别为HTTP服务") Common.LogDebug("Identified as HTTP service")
result.Service.Name = "http" result.Service.Name = "http"
} else { } else {
Common.LogDebug("未知服务") Common.LogDebug("Unknown service")
result.Service.Name = "unknown" result.Service.Name = "unknown"
} }
} else { } else {
Common.LogDebug("使用软匹配结果") Common.LogDebug("Using soft match result")
extras := softMatch.ParseVersionInfo(response) extras := softMatch.ParseVersionInfo(response)
result.Service.Extras = extras.ToMap() result.Service.Extras = extras.ToMap()
result.Service.Name = softMatch.Service result.Service.Name = softMatch.Service
i.Found = true i.Found = true
Common.LogDebug(fmt.Sprintf("软匹配服务: %s", result.Service.Name)) Common.LogDebug(fmt.Sprintf("Soft match service: %s", result.Service.Name))
} }
} }
// Connect 发送数据并获取响应 // Connect sends data and gets response
func (i *Info) Connect(msg []byte) []byte { func (i *Info) Connect(msg []byte) []byte {
i.Write(msg) i.Write(msg)
reply, _ := i.Read() reply, _ := i.Read()
return reply return reply
} }
const WrTimeout = 5 // 默认读写超时时间(秒) const WrTimeout = 5 // Default read/write timeout (seconds)
// Write 写入数据到连接 // Write writes data to the connection
func (i *Info) Write(msg []byte) error { func (i *Info) Write(msg []byte) error {
if i.Conn == nil { if i.Conn == nil {
return nil return nil
} }
// 设置写入超时 // Set write timeout
i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout))) i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
// 写入数据 // Write data
_, err := i.Conn.Write(msg) _, err := i.Conn.Write(msg)
if err != nil && strings.Contains(err.Error(), "close") { if err != nil && strings.Contains(err.Error(), "close") {
i.Conn.Close() i.Conn.Close()
// 连接关闭时重试 // Retry when connection is closed
i.Conn, err = net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second) i.Conn, err = net.DialTimeout("tcp4", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
if err == nil { if err == nil {
i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout))) i.Conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
@ -415,7 +415,7 @@ func (i *Info) Write(msg []byte) error {
} }
} }
// 记录发送的数据 // Record sent data
if err == nil { if err == nil {
i.Result.Send = msg i.Result.Send = msg
} }
@ -423,22 +423,22 @@ func (i *Info) Write(msg []byte) error {
return err return err
} }
// Read 从连接读取响应 // Read reads response from the connection
func (i *Info) Read() ([]byte, error) { func (i *Info) Read() ([]byte, error) {
if i.Conn == nil { if i.Conn == nil {
return nil, nil return nil, nil
} }
// 设置读取超时 // Set read timeout
i.Conn.SetReadDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout))) i.Conn.SetReadDeadline(time.Now().Add(time.Second * time.Duration(WrTimeout)))
// 读取数据 // Read data
result, err := readFromConn(i.Conn) result, err := readFromConn(i.Conn)
if err != nil && strings.Contains(err.Error(), "close") { if err != nil && strings.Contains(err.Error(), "close") {
return result, err return result, err
} }
// 记录接收到的数据 // Record received data
if len(result) > 0 { if len(result) > 0 {
i.Result.Recv = result i.Result.Recv = result
} }
@ -446,9 +446,9 @@ func (i *Info) Read() ([]byte, error) {
return result, err return result, err
} }
// readFromConn 从连接读取数据的辅助函数 // readFromConn helper function to read data from connection
func readFromConn(conn net.Conn) ([]byte, error) { func readFromConn(conn net.Conn) ([]byte, error) {
size := 2 * 1024 // 读取缓冲区大小 size := 2 * 1024 // Read buffer size
var result []byte var result []byte
for { for {
@ -473,4 +473,4 @@ func readFromConn(conn net.Conn) ([]byte, error) {
return result, nil return result, nil
} }
} }
} }

View File

@ -10,47 +10,47 @@ import (
"time" "time"
) )
// Addr 表示待扫描的地址 // Addr represents the address to be scanned
type Addr struct { type Addr struct {
ip string // IP地址 ip string // IP address
port int // 端口号 port int // Port number
} }
// ScanResult 扫描结果 // ScanResult scanning result
type ScanResult struct { type ScanResult struct {
Address string // IP地址 Address string // IP address
Port int // 端口号 Port int // Port number
Service *ServiceInfo // 服务信息 Service *ServiceInfo // Service information
} }
// PortScan 执行端口扫描 // PortScan executes port scanning
// hostslist: 待扫描的主机列表 // hostslist: List of hosts to be scanned
// ports: 待扫描的端口范围 // ports: Port range to be scanned
// timeout: 超时时间(秒) // timeout: Timeout in seconds
// 返回活跃地址列表 // Returns list of active addresses
func PortScan(hostslist []string, ports string, timeout int64) []string { func PortScan(hostslist []string, ports string, timeout int64) []string {
var results []ScanResult var results []ScanResult
var aliveAddrs []string var aliveAddrs []string
var mu sync.Mutex var mu sync.Mutex
// 解析并验证端口列表 // Parse and validate port list
probePorts := Common.ParsePort(ports) probePorts := Common.ParsePort(ports)
if len(probePorts) == 0 { if len(probePorts) == 0 {
Common.LogError(fmt.Sprintf("端口格式错误: %s", ports)) Common.LogError(fmt.Sprintf("Invalid port format: %s", ports))
return aliveAddrs return aliveAddrs
} }
// 排除指定端口 // Exclude specified ports
probePorts = excludeNoPorts(probePorts) probePorts = excludeNoPorts(probePorts)
// 初始化并发控制 // Initialize concurrency control
workers := Common.ThreadNum workers := Common.ThreadNum
addrs := make(chan Addr, 100) // 待扫描地址通道 addrs := make(chan Addr, 100) // Channel for addresses to be scanned
scanResults := make(chan ScanResult, 100) // 扫描结果通道 scanResults := make(chan ScanResult, 100) // Channel for scan results
var wg sync.WaitGroup var wg sync.WaitGroup
var workerWg sync.WaitGroup var workerWg sync.WaitGroup
// 启动扫描工作协程 // Start scanning worker goroutines
for i := 0; i < workers; i++ { for i := 0; i < workers; i++ {
workerWg.Add(1) workerWg.Add(1)
go func() { go func() {
@ -61,7 +61,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
}() }()
} }
// 启动结果处理协程 // Start result processing goroutine
var resultWg sync.WaitGroup var resultWg sync.WaitGroup
resultWg.Add(1) resultWg.Add(1)
go func() { go func() {
@ -75,7 +75,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
} }
}() }()
// 分发扫描任务 // Distribute scanning tasks
for _, port := range probePorts { for _, port := range probePorts {
for _, host := range hostslist { for _, host := range hostslist {
wg.Add(1) wg.Add(1)
@ -83,7 +83,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
} }
} }
// 等待所有任务完成 // Wait for all tasks to complete
close(addrs) close(addrs)
workerWg.Wait() workerWg.Wait()
wg.Wait() wg.Wait()
@ -93,11 +93,11 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
return aliveAddrs return aliveAddrs
} }
// PortConnect 执行单个端口连接检测 // PortConnect performs connection detection for a single port
// addr: 待检测的地址 // addr: Address to be detected
// results: 结果通道 // results: Results channel
// timeout: 超时时间 // timeout: Timeout duration
// wg: 等待组 // wg: Wait group
func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.WaitGroup) { func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
@ -105,7 +105,7 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
var err error var err error
var conn net.Conn var conn net.Conn
// 尝试建立TCP连接 // Try to establish TCP connection
conn, err = Common.WrapperTcpWithTimeout("tcp4", conn, err = Common.WrapperTcpWithTimeout("tcp4",
fmt.Sprintf("%s:%v", addr.ip, addr.port), fmt.Sprintf("%s:%v", addr.ip, addr.port),
time.Duration(timeout)*time.Second) time.Duration(timeout)*time.Second)
@ -118,11 +118,11 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
return return
} }
// 记录开放端口 // Record open port
address := fmt.Sprintf("%s:%d", addr.ip, addr.port) address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
Common.LogSuccess(fmt.Sprintf("端口开放 %s", address)) Common.LogSuccess(fmt.Sprintf("Port open %s", address))
// 保存端口扫描结果 // Save port scan result
portResult := &Common.ScanResult{ portResult := &Common.ScanResult{
Time: time.Now(), Time: time.Now(),
Type: Common.PORT, Type: Common.PORT,
@ -134,66 +134,66 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
} }
Common.SaveResult(portResult) Common.SaveResult(portResult)
// 构造扫描结果 // Construct scan result
result := ScanResult{ result := ScanResult{
Address: addr.ip, Address: addr.ip,
Port: addr.port, Port: addr.port,
} }
// 执行服务识别 // Perform service identification
if !Common.SkipFingerprint && conn != nil { if !Common.SkipFingerprint && conn != nil {
scanner := NewPortInfoScanner(addr.ip, addr.port, conn, time.Duration(timeout)*time.Second) scanner := NewPortInfoScanner(addr.ip, addr.port, conn, time.Duration(timeout)*time.Second)
if serviceInfo, err := scanner.Identify(); err == nil { if serviceInfo, err := scanner.Identify(); err == nil {
result.Service = serviceInfo result.Service = serviceInfo
// 构造服务识别日志 // Construct service identification log
var logMsg strings.Builder var logMsg strings.Builder
logMsg.WriteString(fmt.Sprintf("服务识别 %s => ", address)) logMsg.WriteString(fmt.Sprintf("Service identification %s => ", address))
if serviceInfo.Name != "unknown" { if serviceInfo.Name != "unknown" {
logMsg.WriteString(fmt.Sprintf("[%s]", serviceInfo.Name)) logMsg.WriteString(fmt.Sprintf("[%s]", serviceInfo.Name))
} }
if serviceInfo.Version != "" { if serviceInfo.Version != "" {
logMsg.WriteString(fmt.Sprintf(" 版本:%s", serviceInfo.Version)) logMsg.WriteString(fmt.Sprintf(" Version:%s", serviceInfo.Version))
} }
// 收集服务详细信息 // Collect service details
details := map[string]interface{}{ details := map[string]interface{}{
"port": addr.port, "port": addr.port,
"service": serviceInfo.Name, "service": serviceInfo.Name,
} }
// 添加版本信息 // Add version information
if serviceInfo.Version != "" { if serviceInfo.Version != "" {
details["version"] = serviceInfo.Version details["version"] = serviceInfo.Version
} }
// 添加产品信息 // Add product information
if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" { if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" {
details["product"] = v details["product"] = v
logMsg.WriteString(fmt.Sprintf(" 产品:%s", v)) logMsg.WriteString(fmt.Sprintf(" Product:%s", v))
} }
// 添加操作系统信息 // Add operating system information
if v, ok := serviceInfo.Extras["os"]; ok && v != "" { if v, ok := serviceInfo.Extras["os"]; ok && v != "" {
details["os"] = v details["os"] = v
logMsg.WriteString(fmt.Sprintf(" 系统:%s", v)) logMsg.WriteString(fmt.Sprintf(" OS:%s", v))
} }
// 添加额外信息 // Add additional information
if v, ok := serviceInfo.Extras["info"]; ok && v != "" { if v, ok := serviceInfo.Extras["info"]; ok && v != "" {
details["info"] = v details["info"] = v
logMsg.WriteString(fmt.Sprintf(" 信息:%s", v)) logMsg.WriteString(fmt.Sprintf(" Info:%s", v))
} }
// 添加Banner信息 // Add Banner information
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 { if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
details["banner"] = strings.TrimSpace(serviceInfo.Banner) details["banner"] = strings.TrimSpace(serviceInfo.Banner)
logMsg.WriteString(fmt.Sprintf(" Banner:[%s]", strings.TrimSpace(serviceInfo.Banner))) logMsg.WriteString(fmt.Sprintf(" Banner:[%s]", strings.TrimSpace(serviceInfo.Banner)))
} }
// 保存服务识别结果 // Save service identification result
serviceResult := &Common.ScanResult{ serviceResult := &Common.ScanResult{
Time: time.Now(), Time: time.Now(),
Type: Common.SERVICE, Type: Common.SERVICE,
@ -210,17 +210,17 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
results <- result results <- result
} }
// NoPortScan 生成端口列表(不进行扫描) // NoPortScan generates a port list (without scanning)
// hostslist: 主机列表 // hostslist: Host list
// ports: 端口范围 // ports: Port range
// 返回地址列表 // Returns address list
func NoPortScan(hostslist []string, ports string) []string { func NoPortScan(hostslist []string, ports string) []string {
var AliveAddress []string var AliveAddress []string
// 解析并排除端口 // Parse and exclude ports
probePorts := excludeNoPorts(Common.ParsePort(ports)) probePorts := excludeNoPorts(Common.ParsePort(ports))
// 生成地址列表 // Generate address list
for _, port := range probePorts { for _, port := range probePorts {
for _, host := range hostslist { for _, host := range hostslist {
address := fmt.Sprintf("%s:%d", host, port) address := fmt.Sprintf("%s:%d", host, port)
@ -231,27 +231,27 @@ func NoPortScan(hostslist []string, ports string) []string {
return AliveAddress return AliveAddress
} }
// excludeNoPorts 排除指定的端口 // excludeNoPorts excludes specified ports
// ports: 原始端口列表 // ports: Original port list
// 返回过滤后的端口列表 // Returns filtered port list
func excludeNoPorts(ports []int) []int { func excludeNoPorts(ports []int) []int {
noPorts := Common.ParsePort(Common.ExcludePorts) noPorts := Common.ParsePort(Common.ExcludePorts)
if len(noPorts) == 0 { if len(noPorts) == 0 {
return ports return ports
} }
// 使用map过滤端口 // Use map to filter ports
temp := make(map[int]struct{}) temp := make(map[int]struct{})
for _, port := range ports { for _, port := range ports {
temp[port] = struct{}{} temp[port] = struct{}{}
} }
// 移除需要排除的端口 // Remove ports to be excluded
for _, port := range noPorts { for _, port := range noPorts {
delete(temp, port) delete(temp, port)
} }
// 转换为有序切片 // Convert to ordered slice
var newPorts []int var newPorts []int
for port := range temp { for port := range temp {
newPorts = append(newPorts, port) newPorts = append(newPorts, port)
@ -259,4 +259,4 @@ func excludeNoPorts(ports []int) []int {
sort.Ints(newPorts) sort.Ints(newPorts)
return newPorts return newPorts
} }

View File

@ -5,11 +5,11 @@ import (
"github.com/shadow1ng/fscan/Plugins" "github.com/shadow1ng/fscan/Plugins"
) )
// init 初始化并注册所有扫描插件 // init initializes and registers all scan plugins
// 包括标准端口服务扫描、特殊扫描类型和本地信息收集等 // including standard port service scans, special scan types, and local information collection
func init() { func init() {
// 1. 标准网络服务扫描插件 // 1. Standard network service scan plugins
// 文件传输和远程访问服务 // File transfer and remote access services
Common.RegisterPlugin("ftp", Common.ScanPlugin{ Common.RegisterPlugin("ftp", Common.ScanPlugin{
Name: "FTP", Name: "FTP",
Ports: []int{21}, Ports: []int{21},
@ -28,7 +28,7 @@ func init() {
ScanFunc: Plugins.TelnetScan, ScanFunc: Plugins.TelnetScan,
}) })
// Windows网络服务 // Windows network services
Common.RegisterPlugin("findnet", Common.ScanPlugin{ Common.RegisterPlugin("findnet", Common.ScanPlugin{
Name: "FindNet", Name: "FindNet",
Ports: []int{135}, Ports: []int{135},
@ -47,7 +47,7 @@ func init() {
ScanFunc: Plugins.SmbScan, ScanFunc: Plugins.SmbScan,
}) })
// 数据库服务 // Database services
Common.RegisterPlugin("mssql", Common.ScanPlugin{ Common.RegisterPlugin("mssql", Common.ScanPlugin{
Name: "MSSQL", Name: "MSSQL",
Ports: []int{1433, 1434}, Ports: []int{1433, 1434},
@ -66,7 +66,7 @@ func init() {
ScanFunc: Plugins.MysqlScan, ScanFunc: Plugins.MysqlScan,
}) })
// 中间件和消息队列服务 // Middleware and message queue services
Common.RegisterPlugin("elasticsearch", Common.ScanPlugin{ Common.RegisterPlugin("elasticsearch", Common.ScanPlugin{
Name: "Elasticsearch", Name: "Elasticsearch",
Ports: []int{9200, 9300}, Ports: []int{9200, 9300},
@ -91,14 +91,14 @@ func init() {
ScanFunc: Plugins.ActiveMQScan, ScanFunc: Plugins.ActiveMQScan,
}) })
// 目录和认证服务 // Directory and authentication services
Common.RegisterPlugin("ldap", Common.ScanPlugin{ Common.RegisterPlugin("ldap", Common.ScanPlugin{
Name: "LDAP", Name: "LDAP",
Ports: []int{389, 636}, Ports: []int{389, 636},
ScanFunc: Plugins.LDAPScan, ScanFunc: Plugins.LDAPScan,
}) })
// 邮件服务 // Mail services
Common.RegisterPlugin("smtp", Common.ScanPlugin{ Common.RegisterPlugin("smtp", Common.ScanPlugin{
Name: "SMTP", Name: "SMTP",
Ports: []int{25, 465, 587}, Ports: []int{25, 465, 587},
@ -117,7 +117,7 @@ func init() {
ScanFunc: Plugins.POP3Scan, ScanFunc: Plugins.POP3Scan,
}) })
// 网络管理和监控服务 // Network management and monitoring services
Common.RegisterPlugin("snmp", Common.ScanPlugin{ Common.RegisterPlugin("snmp", Common.ScanPlugin{
Name: "SNMP", Name: "SNMP",
Ports: []int{161, 162}, Ports: []int{161, 162},
@ -130,14 +130,14 @@ func init() {
ScanFunc: Plugins.ModbusScan, ScanFunc: Plugins.ModbusScan,
}) })
// 数据同步和备份服务 // Data synchronization and backup services
Common.RegisterPlugin("rsync", Common.ScanPlugin{ Common.RegisterPlugin("rsync", Common.ScanPlugin{
Name: "Rsync", Name: "Rsync",
Ports: []int{873}, Ports: []int{873},
ScanFunc: Plugins.RsyncScan, ScanFunc: Plugins.RsyncScan,
}) })
// NoSQL数据库 // NoSQL databases
Common.RegisterPlugin("cassandra", Common.ScanPlugin{ Common.RegisterPlugin("cassandra", Common.ScanPlugin{
Name: "Cassandra", Name: "Cassandra",
Ports: []int{9042}, Ports: []int{9042},
@ -150,7 +150,7 @@ func init() {
ScanFunc: Plugins.Neo4jScan, ScanFunc: Plugins.Neo4jScan,
}) })
// 远程桌面和显示服务 // Remote desktop and display services
Common.RegisterPlugin("rdp", Common.ScanPlugin{ Common.RegisterPlugin("rdp", Common.ScanPlugin{
Name: "RDP", Name: "RDP",
Ports: []int{3389, 13389, 33389}, Ports: []int{3389, 13389, 33389},
@ -169,7 +169,7 @@ func init() {
ScanFunc: Plugins.VncScan, ScanFunc: Plugins.VncScan,
}) })
// 缓存和键值存储服务 // Cache and key-value storage services
Common.RegisterPlugin("redis", Common.ScanPlugin{ Common.RegisterPlugin("redis", Common.ScanPlugin{
Name: "Redis", Name: "Redis",
Ports: []int{6379, 6380, 16379}, Ports: []int{6379, 6380, 16379},
@ -194,7 +194,7 @@ func init() {
ScanFunc: Plugins.MongodbScan, ScanFunc: Plugins.MongodbScan,
}) })
// 2. 特殊漏洞扫描插件 // 2. Special vulnerability scan plugins
Common.RegisterPlugin("ms17010", Common.ScanPlugin{ Common.RegisterPlugin("ms17010", Common.ScanPlugin{
Name: "MS17010", Name: "MS17010",
Ports: []int{445}, Ports: []int{445},
@ -207,7 +207,7 @@ func init() {
ScanFunc: Plugins.SmbGhost, ScanFunc: Plugins.SmbGhost,
}) })
// 3. Web应用扫描插件 // 3. Web application scan plugins
Common.RegisterPlugin("webtitle", Common.ScanPlugin{ Common.RegisterPlugin("webtitle", Common.ScanPlugin{
Name: "WebTitle", Name: "WebTitle",
Ports: Common.ParsePortsFromString(Common.WebPorts), Ports: Common.ParsePortsFromString(Common.WebPorts),
@ -220,7 +220,7 @@ func init() {
ScanFunc: Plugins.WebPoc, ScanFunc: Plugins.WebPoc,
}) })
// 4. Windows系统专用插件 // 4. Windows system specific plugins
Common.RegisterPlugin("smb2", Common.ScanPlugin{ Common.RegisterPlugin("smb2", Common.ScanPlugin{
Name: "SMBScan2", Name: "SMBScan2",
Ports: []int{445}, Ports: []int{445},
@ -233,7 +233,7 @@ func init() {
ScanFunc: Plugins.WmiExec, ScanFunc: Plugins.WmiExec,
}) })
// 5. 本地信息收集插件 // 5. Local information collection plugins
Common.RegisterPlugin("localinfo", Common.ScanPlugin{ Common.RegisterPlugin("localinfo", Common.ScanPlugin{
Name: "LocalInfo", Name: "LocalInfo",
Ports: []int{}, Ports: []int{},

View File

@ -13,92 +13,92 @@ import (
"time" "time"
) )
// 全局变量定义 // Global variable definitions
var ( var (
LocalScan bool // 本地扫描模式标识 LocalScan bool // Local scan mode identifier
WebScan bool // Web扫描模式标识 WebScan bool // Web scan mode identifier
) )
// Scan 执行扫描主流程 // Scan executes the main scanning process
// info: 主机信息结构体,包含扫描目标的基本信息 // info: Host information structure, contains basic information about the scan target
func Scan(info Common.HostInfo) { func Scan(info Common.HostInfo) {
Common.LogInfo("开始信息扫描") Common.LogInfo("Starting information scan")
// 初始化HTTP客户端配置 // Initialize HTTP client configuration
lib.Inithttp() lib.Inithttp()
// 初始化并发控制 // Initialize concurrency control
ch := make(chan struct{}, Common.ThreadNum) ch := make(chan struct{}, Common.ThreadNum)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
// 根据扫描模式执行不同的扫描策略 // Execute different scanning strategies based on scan mode
switch { switch {
case Common.LocalMode: case Common.LocalMode:
// 本地信息收集模式 // Local information collection mode
LocalScan = true LocalScan = true
executeLocalScan(info, &ch, &wg) executeLocalScan(info, &ch, &wg)
case len(Common.URLs) > 0: case len(Common.URLs) > 0:
// Web扫描模式 // Web scanning mode
WebScan = true WebScan = true
executeWebScan(info, &ch, &wg) executeWebScan(info, &ch, &wg)
default: default:
// 主机扫描模式 // Host scanning mode
executeHostScan(info, &ch, &wg) executeHostScan(info, &ch, &wg)
} }
// 等待所有扫描任务完成 // Wait for all scanning tasks to complete
finishScan(&wg) finishScan(&wg)
} }
// executeLocalScan 执行本地扫描 // executeLocalScan executes local scanning
// info: 主机信息 // info: Host information
// ch: 并发控制通道 // ch: Concurrency control channel
// wg: 等待组 // wg: Wait group
func executeLocalScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { func executeLocalScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
Common.LogInfo("执行本地信息收集") Common.LogInfo("Executing local information collection")
// 获取本地模式支持的插件列表 // Get list of plugins supported by local mode
validLocalPlugins := getValidPlugins(Common.ModeLocal) validLocalPlugins := getValidPlugins(Common.ModeLocal)
// 验证扫描模式的合法性 // Validate scan mode legality
if err := validateScanMode(validLocalPlugins, Common.ModeLocal); err != nil { if err := validateScanMode(validLocalPlugins, Common.ModeLocal); err != nil {
Common.LogError(err.Error()) Common.LogError(err.Error())
return return
} }
// 输出使用的插件信息 // Output plugin information being used
if Common.ScanMode == Common.ModeLocal { if Common.ScanMode == Common.ModeLocal {
Common.LogInfo("使用全部本地插件") Common.LogInfo("Using all local plugins")
Common.ParseScanMode(Common.ScanMode) Common.ParseScanMode(Common.ScanMode)
} else { } else {
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode)) Common.LogInfo(fmt.Sprintf("Using plugin: %s", Common.ScanMode))
} }
// 执行扫描任务 // Execute scanning tasks
executeScans([]Common.HostInfo{info}, ch, wg) executeScans([]Common.HostInfo{info}, ch, wg)
} }
// executeWebScan 执行Web扫描 // executeWebScan executes Web scanning
// info: 主机信息 // info: Host information
// ch: 并发控制通道 // ch: Concurrency control channel
// wg: 等待组 // wg: Wait group
func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
Common.LogInfo("开始Web扫描") Common.LogInfo("Starting Web scanning")
// 获取Web模式支持的插件列表 // Get list of plugins supported by Web mode
validWebPlugins := getValidPlugins(Common.ModeWeb) validWebPlugins := getValidPlugins(Common.ModeWeb)
// 验证扫描模式的合法性 // Validate scan mode legality
if err := validateScanMode(validWebPlugins, Common.ModeWeb); err != nil { if err := validateScanMode(validWebPlugins, Common.ModeWeb); err != nil {
Common.LogError(err.Error()) Common.LogError(err.Error())
return return
} }
// 处理目标URL列表 // Process target URL list
var targetInfos []Common.HostInfo var targetInfos []Common.HostInfo
for _, url := range Common.URLs { for _, url := range Common.URLs {
urlInfo := info urlInfo := info
// 确保URL包含协议头 // Ensure URL contains protocol header
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
url = "http://" + url url = "http://" + url
} }
@ -106,43 +106,43 @@ func executeWebScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup)
targetInfos = append(targetInfos, urlInfo) targetInfos = append(targetInfos, urlInfo)
} }
// 输出使用的插件信息 // Output plugin information being used
if Common.ScanMode == Common.ModeWeb { if Common.ScanMode == Common.ModeWeb {
Common.LogInfo("使用全部Web插件") Common.LogInfo("Using all Web plugins")
Common.ParseScanMode(Common.ScanMode) Common.ParseScanMode(Common.ScanMode)
} else { } else {
Common.LogInfo(fmt.Sprintf("使用插件: %s", Common.ScanMode)) Common.LogInfo(fmt.Sprintf("Using plugin: %s", Common.ScanMode))
} }
// 执行扫描任务 // Execute scanning tasks
executeScans(targetInfos, ch, wg) executeScans(targetInfos, ch, wg)
} }
// executeHostScan 执行主机扫描 // executeHostScan executes host scanning
// info: 主机信息 // info: Host information
// ch: 并发控制通道 // ch: Concurrency control channel
// wg: 等待组 // wg: Wait group
func executeHostScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { func executeHostScan(info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
// 验证扫描目标 // Validate scan target
if info.Host == "" { if info.Host == "" {
Common.LogError("未指定扫描目标") Common.LogError("Scan target not specified")
return return
} }
// 解析目标主机 // Parse target host
hosts, err := Common.ParseIP(info.Host, Common.HostsFile, Common.ExcludeHosts) hosts, err := Common.ParseIP(info.Host, Common.HostsFile, Common.ExcludeHosts)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("解析主机错误: %v", err)) Common.LogError(fmt.Sprintf("Host parsing error: %v", err))
return return
} }
Common.LogInfo("开始主机扫描") Common.LogInfo("Starting host scanning")
executeScan(hosts, info, ch, wg) executeScan(hosts, info, ch, wg)
} }
// getValidPlugins 获取指定模式下的有效插件列表 // getValidPlugins gets list of valid plugins for the specified mode
// mode: 扫描模式 // mode: Scan mode
// 返回: 有效插件映射表 // returns: Valid plugins mapping table
func getValidPlugins(mode string) map[string]bool { func getValidPlugins(mode string) map[string]bool {
validPlugins := make(map[string]bool) validPlugins := make(map[string]bool)
for _, plugin := range Common.PluginGroups[mode] { for _, plugin := range Common.PluginGroups[mode] {
@ -151,94 +151,94 @@ func getValidPlugins(mode string) map[string]bool {
return validPlugins return validPlugins
} }
// validateScanMode 验证扫描模式的合法性 // validateScanMode validates the legality of scan mode
// validPlugins: 有效插件列表 // validPlugins: Valid plugin list
// mode: 扫描模式 // mode: Scan mode
// 返回: 错误信息 // returns: Error information
func validateScanMode(validPlugins map[string]bool, mode string) error { func validateScanMode(validPlugins map[string]bool, mode string) error {
if Common.ScanMode == "" || Common.ScanMode == "All" { if Common.ScanMode == "" || Common.ScanMode == "All" {
Common.ScanMode = mode Common.ScanMode = mode
} else if _, exists := validPlugins[Common.ScanMode]; !exists { } else if _, exists := validPlugins[Common.ScanMode]; !exists {
return fmt.Errorf("无效的%s插件: %s", mode, Common.ScanMode) return fmt.Errorf("Invalid %s plugin: %s", mode, Common.ScanMode)
} }
return nil return nil
} }
// executeScan 执行主扫描流程 // executeScan executes main scanning process
// hosts: 目标主机列表 // hosts: Target host list
// info: 主机信息 // info: Host information
// ch: 并发控制通道 // ch: Concurrency control channel
// wg: 等待组 // wg: Wait group
func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
var targetInfos []Common.HostInfo var targetInfos []Common.HostInfo
// 处理主机和端口扫描 // Process host and port scanning
if len(hosts) > 0 || len(Common.HostPort) > 0 { if len(hosts) > 0 || len(Common.HostPort) > 0 {
// 检查主机存活性 // Check host liveness
if shouldPingScan(hosts) { if shouldPingScan(hosts) {
hosts = CheckLive(hosts, Common.UsePing) hosts = CheckLive(hosts, Common.UsePing)
Common.LogInfo(fmt.Sprintf("存活主机数量: %d", len(hosts))) Common.LogInfo(fmt.Sprintf("Number of live hosts: %d", len(hosts)))
if Common.IsICMPScan() { if Common.IsICMPScan() {
return return
} }
} }
// 获取存活端口 // Get alive ports
alivePorts := getAlivePorts(hosts) alivePorts := getAlivePorts(hosts)
if len(alivePorts) > 0 { if len(alivePorts) > 0 {
targetInfos = prepareTargetInfos(alivePorts, info) targetInfos = prepareTargetInfos(alivePorts, info)
} }
} }
// 添加URL扫描目标 // Add URL scanning targets
targetInfos = appendURLTargets(targetInfos, info) targetInfos = appendURLTargets(targetInfos, info)
// 执行漏洞扫描 // Execute vulnerability scanning
if len(targetInfos) > 0 { if len(targetInfos) > 0 {
Common.LogInfo("开始漏洞扫描") Common.LogInfo("Starting vulnerability scanning")
executeScans(targetInfos, ch, wg) executeScans(targetInfos, ch, wg)
} }
} }
// shouldPingScan 判断是否需要执行ping扫描 // shouldPingScan determines if ping scanning should be executed
// hosts: 目标主机列表 // hosts: Target host list
// 返回: 是否需要ping扫描 // returns: Whether ping scanning is needed
func shouldPingScan(hosts []string) bool { func shouldPingScan(hosts []string) bool {
return (Common.DisablePing == false && len(hosts) > 1) || Common.IsICMPScan() return (Common.DisablePing == false && len(hosts) > 1) || Common.IsICMPScan()
} }
// getAlivePorts 获取存活端口列表 // getAlivePorts gets list of alive ports
// hosts: 目标主机列表 // hosts: Target host list
// 返回: 存活端口列表 // returns: List of alive ports
func getAlivePorts(hosts []string) []string { func getAlivePorts(hosts []string) []string {
var alivePorts []string var alivePorts []string
// 根据扫描模式选择端口扫描方式 // Choose port scanning method based on scan mode
if Common.IsWebScan() { if Common.IsWebScan() {
alivePorts = NoPortScan(hosts, Common.Ports) alivePorts = NoPortScan(hosts, Common.Ports)
} else if len(hosts) > 0 { } else if len(hosts) > 0 {
alivePorts = PortScan(hosts, Common.Ports, Common.Timeout) alivePorts = PortScan(hosts, Common.Ports, Common.Timeout)
Common.LogInfo(fmt.Sprintf("存活端口数量: %d", len(alivePorts))) Common.LogInfo(fmt.Sprintf("Number of alive ports: %d", len(alivePorts)))
if Common.IsPortScan() { if Common.IsPortScan() {
return nil return nil
} }
} }
// 合并额外指定的端口 // Merge additional specified ports
if len(Common.HostPort) > 0 { if len(Common.HostPort) > 0 {
alivePorts = append(alivePorts, Common.HostPort...) alivePorts = append(alivePorts, Common.HostPort...)
alivePorts = Common.RemoveDuplicate(alivePorts) alivePorts = Common.RemoveDuplicate(alivePorts)
Common.HostPort = nil Common.HostPort = nil
Common.LogInfo(fmt.Sprintf("存活端口数量: %d", len(alivePorts))) Common.LogInfo(fmt.Sprintf("Number of alive ports: %d", len(alivePorts)))
} }
return alivePorts return alivePorts
} }
// appendURLTargets 添加URL扫描目标 // appendURLTargets adds URL scanning targets
// targetInfos: 现有目标列表 // targetInfos: Existing target list
// baseInfo: 基础主机信息 // baseInfo: Base host information
// 返回: 更新后的目标列表 // returns: Updated target list
func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) []Common.HostInfo { func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) []Common.HostInfo {
for _, url := range Common.URLs { for _, url := range Common.URLs {
urlInfo := baseInfo urlInfo := baseInfo
@ -248,16 +248,16 @@ func appendURLTargets(targetInfos []Common.HostInfo, baseInfo Common.HostInfo) [
return targetInfos return targetInfos
} }
// prepareTargetInfos 准备扫描目标信息 // prepareTargetInfos prepares scanning target information
// alivePorts: 存活端口列表 // alivePorts: Alive port list
// baseInfo: 基础主机信息 // baseInfo: Base host information
// 返回: 目标信息列表 // returns: Target information list
func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.HostInfo { func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.HostInfo {
var infos []Common.HostInfo var infos []Common.HostInfo
for _, targetIP := range alivePorts { for _, targetIP := range alivePorts {
hostParts := strings.Split(targetIP, ":") hostParts := strings.Split(targetIP, ":")
if len(hostParts) != 2 { if len(hostParts) != 2 {
Common.LogError(fmt.Sprintf("无效的目标地址格式: %s", targetIP)) Common.LogError(fmt.Sprintf("Invalid target address format: %s", targetIP))
continue continue
} }
info := baseInfo info := baseInfo
@ -268,27 +268,27 @@ func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.
return infos return infos
} }
// ScanTask 扫描任务结构体 // ScanTask scan task structure
type ScanTask struct { type ScanTask struct {
pluginName string // 插件名称 pluginName string // Plugin name
target Common.HostInfo // 目标信息 target Common.HostInfo // Target information
} }
// executeScans 执行扫描任务 // executeScans executes scanning tasks
// targets: 目标列表 // targets: Target list
// ch: 并发控制通道 // ch: Concurrency control channel
// wg: 等待组 // wg: Wait group
func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
mode := Common.GetScanMode() mode := Common.GetScanMode()
// 获取要执行的插件列表 // Get list of plugins to execute
pluginsToRun, isSinglePlugin := getPluginsToRun(mode) pluginsToRun, isSinglePlugin := getPluginsToRun(mode)
var tasks []ScanTask var tasks []ScanTask
actualTasks := 0 actualTasks := 0
loadedPlugins := make([]string, 0) loadedPlugins := make([]string, 0)
// 收集扫描任务 // Collect scanning tasks
for _, target := range targets { for _, target := range targets {
targetPort, _ := strconv.Atoi(target.Ports) targetPort, _ := strconv.Atoi(target.Ports)
for _, pluginName := range pluginsToRun { for _, pluginName := range pluginsToRun {
@ -305,22 +305,22 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
} }
} }
// 处理插件列表 // Process plugin list
finalPlugins := getUniquePlugins(loadedPlugins) finalPlugins := getUniquePlugins(loadedPlugins)
Common.LogInfo(fmt.Sprintf("加载的插件: %s", strings.Join(finalPlugins, ", "))) Common.LogInfo(fmt.Sprintf("Loaded plugins: %s", strings.Join(finalPlugins, ", ")))
// 初始化进度条 // Initialize progress bar
initializeProgressBar(actualTasks) initializeProgressBar(actualTasks)
// 执行扫描任务 // Execute scanning tasks
for _, task := range tasks { for _, task := range tasks {
AddScan(task.pluginName, task.target, ch, wg) AddScan(task.pluginName, task.target, ch, wg)
} }
} }
// getPluginsToRun 获取要执行的插件列表 // getPluginsToRun gets list of plugins to execute
// mode: 扫描模式 // mode: Scan mode
// 返回: 插件列表和是否为单插件模式 // returns: Plugin list and whether it's single plugin mode
func getPluginsToRun(mode string) ([]string, bool) { func getPluginsToRun(mode string) ([]string, bool) {
var pluginsToRun []string var pluginsToRun []string
isSinglePlugin := false isSinglePlugin := false
@ -335,13 +335,13 @@ func getPluginsToRun(mode string) ([]string, bool) {
return pluginsToRun, isSinglePlugin return pluginsToRun, isSinglePlugin
} }
// collectScanTasks 收集扫描任务 // collectScanTasks collects scanning tasks
// plugin: 插件信息 // plugin: Plugin information
// target: 目标信息 // target: Target information
// targetPort: 目标端口 // targetPort: Target port
// pluginName: 插件名称 // pluginName: Plugin name
// isSinglePlugin: 是否为单插件模式 // isSinglePlugin: Whether it's single plugin mode
// 返回: 是否添加任务和任务列表 // returns: Whether task was added and task list
func collectScanTasks(plugin Common.ScanPlugin, target Common.HostInfo, targetPort int, pluginName string, isSinglePlugin bool) (bool, []ScanTask) { func collectScanTasks(plugin Common.ScanPlugin, target Common.HostInfo, targetPort int, pluginName string, isSinglePlugin bool) (bool, []ScanTask) {
var tasks []ScanTask var tasks []ScanTask
taskAdded := false taskAdded := false
@ -357,9 +357,9 @@ func collectScanTasks(plugin Common.ScanPlugin, target Common.HostInfo, targetPo
return taskAdded, tasks return taskAdded, tasks
} }
// getUniquePlugins 获取去重后的插件列表 // getUniquePlugins gets deduplicated plugin list
// loadedPlugins: 已加载的插件列表 // loadedPlugins: Already loaded plugin list
// 返回: 去重并排序后的插件列表 // returns: Deduplicated and sorted plugin list
func getUniquePlugins(loadedPlugins []string) []string { func getUniquePlugins(loadedPlugins []string) []string {
uniquePlugins := make(map[string]struct{}) uniquePlugins := make(map[string]struct{})
for _, p := range loadedPlugins { for _, p := range loadedPlugins {
@ -375,15 +375,15 @@ func getUniquePlugins(loadedPlugins []string) []string {
return finalPlugins return finalPlugins
} }
// initializeProgressBar 初始化进度条 // initializeProgressBar initializes progress bar
// actualTasks: 实际任务数量 // actualTasks: Actual number of tasks
func initializeProgressBar(actualTasks int) { func initializeProgressBar(actualTasks int) {
if Common.ShowProgress { if Common.ShowProgress {
Common.ProgressBar = progressbar.NewOptions(actualTasks, Common.ProgressBar = progressbar.NewOptions(actualTasks,
progressbar.OptionEnableColorCodes(true), progressbar.OptionEnableColorCodes(true),
progressbar.OptionShowCount(), progressbar.OptionShowCount(),
progressbar.OptionSetWidth(15), progressbar.OptionSetWidth(15),
progressbar.OptionSetDescription("[cyan]扫描进度:[reset]"), progressbar.OptionSetDescription("[cyan]Scanning progress:[reset]"),
progressbar.OptionSetTheme(progressbar.Theme{ progressbar.OptionSetTheme(progressbar.Theme{
Saucer: "[green]=[reset]", Saucer: "[green]=[reset]",
SaucerHead: "[green]>[reset]", SaucerHead: "[green]>[reset]",
@ -398,25 +398,25 @@ func initializeProgressBar(actualTasks int) {
} }
} }
// finishScan 完成扫描任务 // finishScan completes scanning tasks
// wg: 等待组 // wg: Wait group
func finishScan(wg *sync.WaitGroup) { func finishScan(wg *sync.WaitGroup) {
wg.Wait() wg.Wait()
if Common.ProgressBar != nil { if Common.ProgressBar != nil {
Common.ProgressBar.Finish() Common.ProgressBar.Finish()
fmt.Println() fmt.Println()
} }
Common.LogSuccess(fmt.Sprintf("扫描已完成: %v/%v", Common.End, Common.Num)) Common.LogSuccess(fmt.Sprintf("Scanning completed: %v/%v", Common.End, Common.Num))
} }
// Mutex 用于保护共享资源的并发访问 // Mutex for protecting concurrent access to shared resources
var Mutex = &sync.Mutex{} var Mutex = &sync.Mutex{}
// AddScan 添加扫描任务并启动扫描 // AddScan adds scanning task and starts scanning
// plugin: 插件名称 // plugin: Plugin name
// info: 目标信息 // info: Target information
// ch: 并发控制通道 // ch: Concurrency control channel
// wg: 等待组 // wg: Wait group
func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
*ch <- struct{}{} *ch <- struct{}{}
wg.Add(1) wg.Add(1)
@ -433,29 +433,29 @@ func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.Wa
}() }()
} }
// ScanFunc 执行扫描插件 // ScanFunc executes scanning plugin
// name: 插件名称 // name: Plugin name
// info: 目标信息 // info: Target information
func ScanFunc(name *string, info *Common.HostInfo) { func ScanFunc(name *string, info *Common.HostInfo) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
Common.LogError(fmt.Sprintf("扫描错误 %v:%v - %v", info.Host, info.Ports, err)) Common.LogError(fmt.Sprintf("Scanning error %v:%v - %v", info.Host, info.Ports, err))
} }
}() }()
plugin, exists := Common.PluginManager[*name] plugin, exists := Common.PluginManager[*name]
if !exists { if !exists {
Common.LogInfo(fmt.Sprintf("扫描类型 %v 无对应插件,已跳过", *name)) Common.LogInfo(fmt.Sprintf("Scan type %v has no corresponding plugin, skipped", *name))
return return
} }
if err := plugin.ScanFunc(info); err != nil { if err := plugin.ScanFunc(info); err != nil {
Common.LogError(fmt.Sprintf("扫描错误 %v:%v - %v", info.Host, info.Ports, err)) Common.LogError(fmt.Sprintf("Scanning error %v:%v - %v", info.Host, info.Ports, err))
} }
} }
// updateScanProgress 更新扫描进度 // updateScanProgress updates scanning progress
// info: 目标信息 // info: Target information
func updateScanProgress(info *Common.HostInfo) { func updateScanProgress(info *Common.HostInfo) {
Common.OutputMutex.Lock() Common.OutputMutex.Lock()
atomic.AddInt64(&Common.End, 1) atomic.AddInt64(&Common.End, 1)
@ -464,4 +464,4 @@ func updateScanProgress(info *Common.HostInfo) {
Common.ProgressBar.Add(1) Common.ProgressBar.Add(1)
} }
Common.OutputMutex.Unlock() Common.OutputMutex.Unlock()
} }