feat: 分离结果输出和日志

This commit is contained in:
ZacharyZcR 2025-01-14 23:38:58 +08:00
parent c6c613a17b
commit 97e9ac7161
38 changed files with 1526 additions and 879 deletions

View File

@ -847,7 +847,10 @@ var PortMap = map[int][]string{
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "Password", "P@ssword123", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789", "elastic123"} var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "Password", "P@ssword123", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789", "elastic123"}
var Outputfile = "result.txt" var (
Outputfile string // 输出文件路径
OutputFormat string // 输出格式
)
// 添加一个全局的进度条变量 // 添加一个全局的进度条变量
var ProgressBar *progressbar.ProgressBar var ProgressBar *progressbar.ProgressBar

View File

@ -160,6 +160,7 @@ func Flag(Info *HostInfo) {
// 输出配置 // 输出配置
flag.StringVar(&Outputfile, "o", "result.txt", "指定结果输出文件名") flag.StringVar(&Outputfile, "o", "result.txt", "指定结果输出文件名")
flag.StringVar(&OutputFormat, "f", "txt", "指定输出格式 (txt/json/csv)")
flag.BoolVar(&DisableSave, "no", false, "禁止保存扫描结果") flag.BoolVar(&DisableSave, "no", false, "禁止保存扫描结果")
flag.BoolVar(&Silent, "silent", false, "启用静默扫描模式(减少屏幕输出)") flag.BoolVar(&Silent, "silent", false, "启用静默扫描模式(减少屏幕输出)")
flag.BoolVar(&NoColor, "nocolor", false, "禁用彩色输出显示") flag.BoolVar(&NoColor, "nocolor", false, "禁用彩色输出显示")

View File

@ -1,12 +1,9 @@
package Common package Common
import ( import (
"bufio"
"encoding/json"
"fmt" "fmt"
"io" "io"
"log" "log"
"os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
@ -16,118 +13,123 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
) )
// 全局变量定义
var ( var (
// 全局变量 // 扫描状态管理器,记录最近一次成功和错误的时间
status = &ScanStatus{lastSuccess: time.Now(), lastError: time.Now()} status = &ScanStatus{lastSuccess: time.Now(), lastError: time.Now()}
// 扫描计数 // Num 表示待处理的总任务数量
Num int64 // 总任务数 Num int64
End int64 // 已完成任务数 // End 表示已经完成的任务数量
End int64
// 文件写入器
fileWriter *bufferedFileWriter
) )
// ScanStatus 记录扫描状态 // ScanStatus 用于记录和管理扫描状态的结构体
type ScanStatus struct { type ScanStatus struct {
mu sync.RWMutex mu sync.RWMutex // 读写互斥锁,用于保护并发访问
total int64 total int64 // 总任务数
completed int64 completed int64 // 已完成任务数
lastSuccess time.Time lastSuccess time.Time // 最近一次成功的时间
lastError time.Time lastError time.Time // 最近一次错误的时间
} }
// LogEntry 日志条目 // LogEntry 定义单条日志的结构
type LogEntry struct { type LogEntry struct {
Level string // "ERROR", "INFO", "SUCCESS", "DEBUG" Level string // 日志级别: ERROR/INFO/SUCCESS/DEBUG
Time time.Time Time time.Time // 日志时间
Content string Content string // 日志内容
} }
// LogLevel 定义日志级常量 // 定义系统支持的日志级常量
const ( const (
LogLevelAll = "ALL" // 输出所有日志 LogLevelAll = "ALL" // 显示所有级别日志
LogLevelError = "ERROR" // 错误日志 LogLevelError = "ERROR" // 仅显示错误日志
LogLevelInfo = "INFO" // 信息日志 LogLevelInfo = "INFO" // 仅显示信息日志
LogLevelSuccess = "SUCCESS" // 成功日志 LogLevelSuccess = "SUCCESS" // 仅显示成功日志
LogLevelDebug = "DEBUG" // 调试日志 LogLevelDebug = "DEBUG" // 仅显示调试日志
) )
// 定义日志颜色映射 // 日志级别对应的显示颜色映射
var logColors = map[string]color.Attribute{ var logColors = map[string]color.Attribute{
LogLevelError: color.FgRed, LogLevelError: color.FgRed, // 错误日志显示红色
LogLevelInfo: color.FgYellow, LogLevelInfo: color.FgYellow, // 信息日志显示黄色
LogLevelSuccess: color.FgGreen, LogLevelSuccess: color.FgGreen, // 成功日志显示绿色
LogLevelDebug: color.FgBlue, LogLevelDebug: color.FgBlue, // 调试日志显示蓝色
}
// JsonOutput JSON输出的结构体
type JsonOutput struct {
Level string `json:"level"`
Timestamp time.Time `json:"timestamp"`
Message string `json:"message"`
} }
// InitLogger 初始化日志系统
func InitLogger() { func InitLogger() {
// 禁用标准日志输出
log.SetOutput(io.Discard) log.SetOutput(io.Discard)
if !DisableSave {
fileWriter = newBufferedFileWriter()
}
} }
// formatLogMessage 格式化日志消息 // formatLogMessage 格式化日志消息为标准格式
// 返回格式:[时间] [级别] 内容
func formatLogMessage(entry *LogEntry) string { func formatLogMessage(entry *LogEntry) string {
timeStr := entry.Time.Format("2006-01-02 15:04:05") timeStr := entry.Time.Format("2006-01-02 15:04:05")
return fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Content) return fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Content)
} }
// 修改 printLog 函数 // printLog 根据日志级别打印日志
func printLog(entry *LogEntry) { func printLog(entry *LogEntry) {
// 默认情况(LogLevelInfo)下打印 INFO、SUCCESS、ERROR // 根据当前设置的日志级别过滤日志
if LogLevel == LogLevelInfo { switch LogLevel {
case LogLevelInfo:
// INFO模式下只打印 INFO、SUCCESS、ERROR 级别的日志
if entry.Level != LogLevelInfo && if entry.Level != LogLevelInfo &&
entry.Level != LogLevelSuccess && entry.Level != LogLevelSuccess &&
entry.Level != LogLevelError { entry.Level != LogLevelError {
return return
} }
} else if LogLevel == LogLevelDebug || LogLevel == LogLevelAll { case LogLevelDebug, LogLevelAll:
// Debug或ALL模式打印所有日志 // Debug或ALL模式下打印所有日志
} else if entry.Level != LogLevel { default:
// 其他情况只打印指定等级的日志 // 其他模式下只打印指定级别的日志
if entry.Level != LogLevel {
return return
} }
}
OutputMutex.Lock() OutputMutex.Lock()
defer OutputMutex.Unlock() defer OutputMutex.Unlock()
// 确保清除当前进度条 // 处理进度条
if ProgressBar != nil { clearAndWaitProgress()
ProgressBar.Clear()
time.Sleep(10 * time.Millisecond)
}
// 打印日志 // 打印日志消息
logMsg := formatLogMessage(entry) logMsg := formatLogMessage(entry)
if !NoColor { if !NoColor {
// 使用彩色输出
if colorAttr, ok := logColors[entry.Level]; ok { if colorAttr, ok := logColors[entry.Level]; ok {
color.New(colorAttr).Println(logMsg) color.New(colorAttr).Println(logMsg)
} else { } else {
fmt.Println(logMsg) fmt.Println(logMsg)
} }
} else { } else {
// 普通输出
fmt.Println(logMsg) fmt.Println(logMsg)
} }
// 确保日志完全输出 // 等待日志输出完成
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
// 重新渲染进度条 // 重新显示进度条
if ProgressBar != nil { if ProgressBar != nil {
ProgressBar.RenderBlank() ProgressBar.RenderBlank()
} }
} }
// clearAndWaitProgress 清除进度条并等待
func clearAndWaitProgress() {
if ProgressBar != nil {
ProgressBar.Clear()
time.Sleep(10 * time.Millisecond)
}
}
// LogError 记录错误日志,自动包含文件名和行号信息
func LogError(errMsg string) { func LogError(errMsg string) {
// 获取调用者的文件名和行号
_, file, line, ok := runtime.Caller(1) _, file, line, ok := runtime.Caller(1)
if !ok { if !ok {
file = "unknown" file = "unknown"
@ -137,182 +139,60 @@ func LogError(errMsg string) {
errorMsg := fmt.Sprintf("%s:%d - %s", file, line, errMsg) errorMsg := fmt.Sprintf("%s:%d - %s", file, line, errMsg)
if ProgressBar != nil {
ProgressBar.Clear()
}
entry := &LogEntry{ entry := &LogEntry{
Level: LogLevelError, Level: LogLevelError,
Time: time.Now(), Time: time.Now(),
Content: errorMsg, Content: errorMsg,
} }
printLog(entry) handleLog(entry)
if fileWriter != nil { }
fileWriter.write(entry)
// handleLog 统一处理日志的输出
func handleLog(entry *LogEntry) {
if ProgressBar != nil {
ProgressBar.Clear()
} }
printLog(entry)
if ProgressBar != nil { if ProgressBar != nil {
ProgressBar.RenderBlank() ProgressBar.RenderBlank()
} }
} }
// LogInfo 记录信息日志
func LogInfo(msg string) { func LogInfo(msg string) {
if ProgressBar != nil { handleLog(&LogEntry{
ProgressBar.Clear()
}
entry := &LogEntry{
Level: LogLevelInfo, Level: LogLevelInfo,
Time: time.Now(), Time: time.Now(),
Content: msg, Content: msg,
} })
printLog(entry)
if fileWriter != nil {
fileWriter.write(entry)
}
if ProgressBar != nil {
ProgressBar.RenderBlank()
}
} }
// LogSuccess 记录成功日志,并更新最后成功时间
func LogSuccess(result string) { func LogSuccess(result string) {
if ProgressBar != nil {
ProgressBar.Clear()
}
entry := &LogEntry{ entry := &LogEntry{
Level: LogLevelSuccess, Level: LogLevelSuccess,
Time: time.Now(), Time: time.Now(),
Content: result, Content: result,
} }
printLog(entry) handleLog(entry)
if fileWriter != nil {
fileWriter.write(entry)
}
// 更新最后成功时间
status.mu.Lock() status.mu.Lock()
status.lastSuccess = time.Now() status.lastSuccess = time.Now()
status.mu.Unlock() status.mu.Unlock()
if ProgressBar != nil {
ProgressBar.RenderBlank()
}
} }
// LogDebug 记录调试日志
func LogDebug(msg string) { func LogDebug(msg string) {
if ProgressBar != nil { handleLog(&LogEntry{
ProgressBar.Clear()
}
entry := &LogEntry{
Level: LogLevelDebug, Level: LogLevelDebug,
Time: time.Now(), Time: time.Now(),
Content: msg, Content: msg,
} })
printLog(entry)
if fileWriter != nil {
fileWriter.write(entry)
}
if ProgressBar != nil {
ProgressBar.RenderBlank()
}
}
func newBufferedFileWriter() *bufferedFileWriter {
file, err := os.OpenFile(Outputfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Printf("[ERROR] 打开输出文件失败 %s: %v\n", Outputfile, err)
return nil
}
writer := bufio.NewWriter(file)
return &bufferedFileWriter{
file: file,
writer: writer,
jsonEnc: json.NewEncoder(writer),
}
}
type bufferedFileWriter struct {
file *os.File
writer *bufio.Writer
jsonEnc *json.Encoder
mu sync.Mutex // 添加互斥锁保护写入
}
func (w *bufferedFileWriter) write(entry *LogEntry) {
if w == nil {
return
}
w.mu.Lock()
defer w.mu.Unlock()
var err error
if JsonFormat {
output := JsonOutput{
Level: entry.Level,
Timestamp: entry.Time,
Message: entry.Content,
}
err = w.jsonEnc.Encode(output)
} else {
logMsg := formatLogMessage(entry) + "\n"
_, err = w.writer.WriteString(logMsg)
}
if err != nil {
fmt.Printf("[ERROR] 写入日志失败: %v\n", err)
// 尝试重新打开文件
if err := w.reopen(); err != nil {
fmt.Printf("[ERROR] 重新打开文件失败: %v\n", err)
return
}
return
}
// 每隔一定数量的写入才进行一次Flush
if err := w.writer.Flush(); err != nil {
fmt.Printf("[ERROR] 刷新缓冲区失败: %v\n", err)
if err := w.reopen(); err != nil {
fmt.Printf("[ERROR] 重新打开文件失败: %v\n", err)
}
}
}
func (w *bufferedFileWriter) reopen() error {
if w.file != nil {
w.file.Close()
}
file, err := os.OpenFile(Outputfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return err
}
w.file = file
w.writer = bufio.NewWriter(file)
w.jsonEnc = json.NewEncoder(w.writer)
return nil
}
func (w *bufferedFileWriter) close() {
if w != nil {
w.writer.Flush()
w.file.Close()
}
}
func CloseLogger() {
if fileWriter != nil {
fileWriter.close()
}
} }
// CheckErrs 检查是否为需要重试的错误 // CheckErrs 检查是否为需要重试的错误

247
Common/Output.go Normal file
View File

@ -0,0 +1,247 @@
// output.go
package Common
import (
"encoding/csv"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"sync"
"time"
)
// 全局输出管理器
var ResultOutput *OutputManager
// OutputManager 输出管理器结构体
type OutputManager struct {
mu sync.Mutex
outputPath string
outputFormat string
file *os.File
csvWriter *csv.Writer
jsonEncoder *json.Encoder
isInitialized bool
}
// ResultType 定义结果类型
type ResultType string
const (
HOST ResultType = "HOST" // 主机存活
PORT ResultType = "PORT" // 端口开放
SERVICE ResultType = "SERVICE" // 服务识别
VULN ResultType = "VULN" // 漏洞发现
)
// ScanResult 扫描结果结构
type ScanResult struct {
Time time.Time `json:"time"` // 发现时间
Type ResultType `json:"type"` // 结果类型
Target string `json:"target"` // 目标(IP/域名/URL)
Status string `json:"status"` // 状态描述
Details map[string]interface{} `json:"details"` // 详细信息
}
// InitOutput 初始化输出系统
func InitOutput() error {
LogDebug("开始初始化输出系统")
// 验证输出格式
switch OutputFormat {
case "txt", "json", "csv":
// 有效的格式
default:
return fmt.Errorf("不支持的输出格式: %s", OutputFormat)
}
// 验证输出路径
if Outputfile == "" {
return fmt.Errorf("输出文件路径不能为空")
}
dir := filepath.Dir(Outputfile)
if err := os.MkdirAll(dir, 0755); err != nil {
LogDebug(fmt.Sprintf("创建输出目录失败: %v", err))
return fmt.Errorf("创建输出目录失败: %v", err)
}
manager := &OutputManager{
outputPath: Outputfile,
outputFormat: OutputFormat,
}
if err := manager.initialize(); err != nil {
LogDebug(fmt.Sprintf("初始化输出管理器失败: %v", err))
return fmt.Errorf("初始化输出管理器失败: %v", err)
}
ResultOutput = manager
LogDebug("输出系统初始化完成")
return nil
}
func (om *OutputManager) initialize() error {
om.mu.Lock()
defer om.mu.Unlock()
if om.isInitialized {
LogDebug("输出管理器已经初始化,跳过")
return nil
}
LogDebug(fmt.Sprintf("正在打开输出文件: %s", om.outputPath))
file, err := os.OpenFile(om.outputPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
LogDebug(fmt.Sprintf("打开输出文件失败: %v", err))
return fmt.Errorf("打开输出文件失败: %v", err)
}
om.file = file
switch om.outputFormat {
case "csv":
LogDebug("初始化CSV写入器")
om.csvWriter = csv.NewWriter(file)
headers := []string{"Time", "Type", "Target", "Status", "Details"}
if err := om.csvWriter.Write(headers); err != nil {
LogDebug(fmt.Sprintf("写入CSV头失败: %v", err))
file.Close()
return fmt.Errorf("写入CSV头失败: %v", err)
}
om.csvWriter.Flush()
case "json":
LogDebug("初始化JSON编码器")
om.jsonEncoder = json.NewEncoder(file)
om.jsonEncoder.SetIndent("", " ")
case "txt":
LogDebug("初始化文本输出")
default:
LogDebug(fmt.Sprintf("不支持的输出格式: %s", om.outputFormat))
}
om.isInitialized = true
LogDebug("输出管理器初始化完成")
return nil
}
// SaveResult 保存扫描结果
func SaveResult(result *ScanResult) error {
if ResultOutput == nil {
LogDebug("输出系统未初始化")
return fmt.Errorf("输出系统未初始化")
}
LogDebug(fmt.Sprintf("正在保存结果 - 类型: %s, 目标: %s", result.Type, result.Target))
return ResultOutput.saveResult(result)
}
func (om *OutputManager) saveResult(result *ScanResult) error {
om.mu.Lock()
defer om.mu.Unlock()
if !om.isInitialized {
LogDebug("输出管理器未初始化")
return fmt.Errorf("输出管理器未初始化")
}
var err error
switch om.outputFormat {
case "txt":
err = om.writeTxt(result)
case "json":
err = om.writeJson(result)
case "csv":
err = om.writeCsv(result)
default:
LogDebug(fmt.Sprintf("不支持的输出格式: %s", om.outputFormat))
return fmt.Errorf("不支持的输出格式: %s", om.outputFormat)
}
if err != nil {
LogDebug(fmt.Sprintf("保存结果失败: %v", err))
} else {
LogDebug(fmt.Sprintf("成功保存结果 - 类型: %s, 目标: %s", result.Type, result.Target))
}
return err
}
func (om *OutputManager) writeTxt(result *ScanResult) error {
// 格式化 Details 为键值对字符串
var details string
if len(result.Details) > 0 {
pairs := make([]string, 0, len(result.Details))
for k, v := range result.Details {
pairs = append(pairs, fmt.Sprintf("%s=%v", k, v))
}
details = strings.Join(pairs, ", ")
}
txt := fmt.Sprintf("[%s] [%s] Target: %s, Status: %s, Details: {%s}\n",
result.Time.Format("2006-01-02 15:04:05"),
result.Type,
result.Target,
result.Status,
details,
)
_, err := om.file.WriteString(txt)
return err
}
func (om *OutputManager) writeJson(result *ScanResult) error {
return om.jsonEncoder.Encode(result)
}
func (om *OutputManager) writeCsv(result *ScanResult) error {
details, err := json.Marshal(result.Details)
if err != nil {
details = []byte("{}")
}
record := []string{
result.Time.Format("2006-01-02 15:04:05"),
string(result.Type),
result.Target,
result.Status,
string(details),
}
if err := om.csvWriter.Write(record); err != nil {
return err
}
om.csvWriter.Flush()
return om.csvWriter.Error()
}
// CloseOutput 关闭输出系统
func CloseOutput() error {
if ResultOutput == nil {
LogDebug("输出系统未初始化,无需关闭")
return nil
}
LogDebug("正在关闭输出系统")
ResultOutput.mu.Lock()
defer ResultOutput.mu.Unlock()
if !ResultOutput.isInitialized {
LogDebug("输出管理器未初始化,无需关闭")
return nil
}
if ResultOutput.csvWriter != nil {
LogDebug("刷新CSV写入器缓冲区")
ResultOutput.csvWriter.Flush()
}
if err := ResultOutput.file.Close(); err != nil {
LogDebug(fmt.Sprintf("关闭文件失败: %v", err))
return fmt.Errorf("关闭文件失败: %v", err)
}
ResultOutput.isInitialized = false
LogDebug("输出系统已关闭")
return nil
}

View File

@ -45,22 +45,33 @@ func CheckLive(hostslist []string, Ping bool) []string {
return AliveHosts return AliveHosts
} }
// handleAliveHosts 处理存活主机信息
func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) { func handleAliveHosts(chanHosts chan string, hostslist []string, isPing bool) {
for ip := range chanHosts { for ip := range chanHosts {
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) { if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
ExistHosts[ip] = struct{}{} ExistHosts[ip] = struct{}{}
AliveHosts = append(AliveHosts, ip)
// 输出存活信息 // 使用Output系统保存存活主机信息
if !Common.Silent {
protocol := "ICMP" protocol := "ICMP"
if isPing { if isPing {
protocol = "PING" protocol = "PING"
} }
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.HOST,
Target: ip,
Status: "alive",
Details: map[string]interface{}{
"protocol": protocol,
},
}
Common.SaveResult(result)
// 保留原有的控制台输出
if !Common.Silent {
Common.LogSuccess(fmt.Sprintf("目标 %-15s 存活 (%s)", ip, protocol)) Common.LogSuccess(fmt.Sprintf("目标 %-15s 存活 (%s)", ip, protocol))
} }
AliveHosts = append(AliveHosts, ip)
} }
livewg.Done() livewg.Done()
} }

View File

@ -110,18 +110,31 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
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("端口开放 %s", address))
// 保存端口开放信息
portResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.PORT,
Target: addr.ip,
Status: "open",
Details: map[string]interface{}{
"port": addr.port,
},
}
Common.SaveResult(portResult)
// 创建扫描结果 // 创建扫描结果
result := ScanResult{ result := ScanResult{
Address: addr.ip, Address: addr.ip,
Port: addr.port, Port: addr.port,
} }
// 只在未跳过指纹识别时进行服务识别 // 服务识别
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
// 构造日志消息
var logMsg strings.Builder var logMsg strings.Builder
logMsg.WriteString(fmt.Sprintf("服务识别 %s => ", address)) logMsg.WriteString(fmt.Sprintf("服务识别 %s => ", address))
@ -133,20 +146,42 @@ func PortConnect(addr Addr, results chan<- ScanResult, timeout int64, wg *sync.W
logMsg.WriteString(fmt.Sprintf(" 版本:%s", serviceInfo.Version)) logMsg.WriteString(fmt.Sprintf(" 版本:%s", serviceInfo.Version))
} }
// 构造服务详情
details := map[string]interface{}{
"port": addr.port,
"service": serviceInfo.Name,
}
if serviceInfo.Version != "" {
details["version"] = serviceInfo.Version
}
if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" { if v, ok := serviceInfo.Extras["vendor_product"]; ok && v != "" {
details["product"] = v
logMsg.WriteString(fmt.Sprintf(" 产品:%s", v)) logMsg.WriteString(fmt.Sprintf(" 产品:%s", v))
} }
if v, ok := serviceInfo.Extras["os"]; ok && v != "" { if v, ok := serviceInfo.Extras["os"]; ok && v != "" {
details["os"] = v
logMsg.WriteString(fmt.Sprintf(" 系统:%s", v)) logMsg.WriteString(fmt.Sprintf(" 系统:%s", v))
} }
if v, ok := serviceInfo.Extras["info"]; ok && v != "" { if v, ok := serviceInfo.Extras["info"]; ok && v != "" {
details["info"] = v
logMsg.WriteString(fmt.Sprintf(" 信息:%s", v)) logMsg.WriteString(fmt.Sprintf(" 信息:%s", v))
} }
if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 { if len(serviceInfo.Banner) > 0 && len(serviceInfo.Banner) < 100 {
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)))
} }
// 保存服务识别结果
serviceResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.SERVICE,
Target: addr.ip,
Status: "identified",
Details: details,
}
Common.SaveResult(serviceResult)
Common.LogSuccess(logMsg.String()) Common.LogSuccess(logMsg.String())
} }
} }
@ -198,164 +233,3 @@ func excludeNoPorts(ports []int) []int {
return newPorts return newPorts
} }
//func SynScan(ip string, port int, timeout int64) (bool, error) {
// ifName := getInterfaceName()
//
// sendConn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
// if err != nil {
// return false, fmt.Errorf("发送套接字错误: %v", err)
// }
// defer sendConn.Close()
//
// rawConn, err := ipv4.NewRawConn(sendConn)
// if err != nil {
// return false, fmt.Errorf("原始连接错误: %v", err)
// }
//
// dstIP := net.ParseIP(ip)
// if dstIP == nil {
// return false, fmt.Errorf("IP地址无效: %s", ip)
// }
//
// handle, err := pcap.OpenLive(ifName, 65536, true, pcap.BlockForever)
// if err != nil {
// ifaces, err := pcap.FindAllDevs()
// if err != nil {
// return false, fmt.Errorf("网络接口错误: %v", err)
// }
//
// var found bool
// for _, iface := range ifaces {
// handle, err = pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever)
// if err == nil {
// found = true
// break
// }
// }
//
// if !found {
// return false, fmt.Errorf("未找到可用网络接口")
// }
// }
// defer handle.Close()
//
// srcPort := 12345 + port
// filter := fmt.Sprintf("tcp and src port %d and dst port %d", port, srcPort)
// if err := handle.SetBPFFilter(filter); err != nil {
// return false, fmt.Errorf("过滤器错误: %v", err)
// }
//
// // TCP头部设置保持不变
// tcpHeader := &ipv4.Header{
// Version: 4,
// Len: 20,
// TotalLen: 40,
// TTL: 64,
// Protocol: 6,
// Dst: dstIP,
// }
//
// // SYN包构造保持不变
// synPacket := make([]byte, 20)
// binary.BigEndian.PutUint16(synPacket[0:2], uint16(srcPort))
// binary.BigEndian.PutUint16(synPacket[2:4], uint16(port))
// binary.BigEndian.PutUint32(synPacket[4:8], uint32(1))
// binary.BigEndian.PutUint32(synPacket[8:12], uint32(0))
// synPacket[12] = 0x50
// synPacket[13] = 0x02
// binary.BigEndian.PutUint16(synPacket[14:16], uint16(8192))
// binary.BigEndian.PutUint16(synPacket[16:18], uint16(0))
// binary.BigEndian.PutUint16(synPacket[18:20], uint16(0))
//
// checksum := calculateTCPChecksum(synPacket, tcpHeader.Src, tcpHeader.Dst)
// binary.BigEndian.PutUint16(synPacket[16:18], checksum)
//
// if err := rawConn.WriteTo(tcpHeader, synPacket, nil); err != nil {
// return false, fmt.Errorf("SYN包发送错误: %v", err)
// }
//
// packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
// packetSource.DecodeOptions.Lazy = true
// packetSource.NoCopy = true
//
// timeoutChan := time.After(time.Duration(timeout) * time.Second)
//
// for {
// select {
// case packet := <-packetSource.Packets():
// tcpLayer := packet.Layer(layers.LayerTypeTCP)
// if tcpLayer == nil {
// continue
// }
//
// tcp, ok := tcpLayer.(*layers.TCP)
// if !ok {
// continue
// }
//
// if tcp.SYN && tcp.ACK {
// return true, nil
// }
//
// if tcp.RST {
// return false, nil
// }
//
// case <-timeoutChan:
// return false, nil
// }
// }
//}
//
//// calculateTCPChecksum 计算TCP校验和
//func calculateTCPChecksum(tcpHeader []byte, srcIP, dstIP net.IP) uint16 {
// // 创建伪首部
// pseudoHeader := make([]byte, 12)
// copy(pseudoHeader[0:4], srcIP.To4())
// copy(pseudoHeader[4:8], dstIP.To4())
// pseudoHeader[8] = 0
// pseudoHeader[9] = 6 // TCP协议号
// pseudoHeader[10] = byte(len(tcpHeader) >> 8)
// pseudoHeader[11] = byte(len(tcpHeader))
//
// // 计算校验和
// var sum uint32
//
// // 计算伪首部的校验和
// for i := 0; i < len(pseudoHeader)-1; i += 2 {
// sum += uint32(pseudoHeader[i])<<8 | uint32(pseudoHeader[i+1])
// }
//
// // 计算TCP头的校验和
// for i := 0; i < len(tcpHeader)-1; i += 2 {
// sum += uint32(tcpHeader[i])<<8 | uint32(tcpHeader[i+1])
// }
//
// // 如果长度为奇数,处理最后一个字节
// if len(tcpHeader)%2 == 1 {
// sum += uint32(tcpHeader[len(tcpHeader)-1]) << 8
// }
//
// // 将高16位加到低16位
// for sum > 0xffff {
// sum = (sum >> 16) + (sum & 0xffff)
// }
//
// // 取反
// return ^uint16(sum)
//}
//
//// 获取系统对应的接口名
//func getInterfaceName() string {
// switch runtime.GOOS {
// case "windows":
// return "\\Device\\NPF_Loopback"
// case "linux":
// return "lo"
// case "darwin":
// return "lo0"
// default:
// return "lo"
// }
//}

View File

@ -14,8 +14,9 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试默认账户 admin:admin") Common.LogDebug("尝试默认账户 admin:admin")
// 首先测试默认账户 // 首先测试默认账户
@ -26,13 +27,29 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
flag, err := ActiveMQConn(info, "admin", "admin") flag, err := ActiveMQConn(info, "admin", "admin")
if flag { if flag {
Common.LogSuccess(fmt.Sprintf("ActiveMQ服务 %v:%v 成功爆破 用户名: admin 密码: admin", successMsg := fmt.Sprintf("ActiveMQ服务 %s 成功爆破 用户名: admin 密码: admin", target)
info.Host, info.Ports)) Common.LogSuccess(successMsg)
// 保存结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "activemq",
"username": "admin",
"password": "admin",
"type": "weak-password",
},
}
Common.SaveResult(result)
return nil return nil
} }
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("ActiveMQ服务 %v:%v 默认账户尝试失败: %v", errMsg := fmt.Sprintf("ActiveMQ服务 %s 默认账户尝试失败: %v", target, err)
info.Host, info.Ports, err)) Common.LogError(errMsg)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
@ -46,8 +63,7 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
totalUsers := len(Common.Userdict["activemq"]) totalUsers := len(Common.Userdict["activemq"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
totalUsers, totalPass))
tried := 0 tried := 0
total := totalUsers * totalPass total := totalUsers * totalPass
@ -65,7 +81,6 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行连接测试
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -82,14 +97,29 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success { if result.success {
Common.LogSuccess(fmt.Sprintf("ActiveMQ服务 %v:%v 成功爆破 用户名: %v 密码: %v", successMsg := fmt.Sprintf("ActiveMQ服务 %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
info.Host, info.Ports, user, pass)) Common.LogSuccess(successMsg)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "activemq",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
@ -97,9 +127,8 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errMsg := fmt.Sprintf("ActiveMQ服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err) Common.LogError(errMsg)
Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
@ -149,14 +178,10 @@ func ActiveMQConn(info *Common.HostInfo, user string, pass string) (bool, error)
response := string(respBuf[:n]) response := string(respBuf[:n])
if strings.Contains(response, "CONNECTED") { if strings.Contains(response, "CONNECTED") {
result := fmt.Sprintf("ActiveMQ服务 %v:%v 爆破成功 用户名: %v 密码: %v",
info.Host, info.Ports, user, pass)
Common.LogSuccess(result)
return true, nil return true, nil
} }
if strings.Contains(response, "Authentication failed") || if strings.Contains(response, "Authentication failed") || strings.Contains(response, "ERROR") {
strings.Contains(response, "ERROR") {
return false, fmt.Errorf("认证失败") return false, fmt.Errorf("认证失败")
} }

View File

@ -14,9 +14,10 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
return return
} }
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试无认证访问...") Common.LogDebug("尝试无认证访问...")
// 首先测试无认证访问 // 首先测试无认证访问
@ -27,8 +28,24 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
flag, err := CassandraConn(info, "", "") flag, err := CassandraConn(info, "", "")
if flag && err == nil { if flag && err == nil {
Common.LogSuccess(fmt.Sprintf("Cassandra服务 %v:%v 无认证访问成功", successMsg := fmt.Sprintf("Cassandra服务 %s 无认证访问成功", target)
info.Host, info.Ports)) Common.LogSuccess(successMsg)
// 保存无认证访问结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "cassandra",
"auth_type": "anonymous",
"type": "unauthorized-access",
"description": "数据库允许无认证访问",
},
}
Common.SaveResult(result)
return err return err
} }
if err != nil && Common.CheckErrs(err) != nil { if err != nil && Common.CheckErrs(err) != nil {
@ -54,13 +71,11 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass)) Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -77,37 +92,47 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
successLog := fmt.Sprintf("Cassandra服务 %v:%v 爆破成功 用户名: %v 密码: %v", successMsg := fmt.Sprintf("Cassandra服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass)
info.Host, info.Ports, user, pass) Common.LogSuccess(successMsg)
Common.LogSuccess(successLog)
// 保存爆破成功结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "cassandra",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Cassandra服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break
break // 如果不需要重试,跳出重试循环
} }
} }
} }
@ -116,6 +141,7 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
return tmperr return tmperr
} }
// CassandraConn 清理后的连接测试函数
func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error) { func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error) {
host, port := info.Host, info.Ports host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
@ -123,7 +149,7 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
cluster := gocql.NewCluster(host) cluster := gocql.NewCluster(host)
cluster.Port, _ = strconv.Atoi(port) cluster.Port, _ = strconv.Atoi(port)
cluster.Timeout = timeout cluster.Timeout = timeout
cluster.ProtoVersion = 4 // 指定协议版本 cluster.ProtoVersion = 4
cluster.Consistency = gocql.One cluster.Consistency = gocql.One
if user != "" || pass != "" { if user != "" || pass != "" {
@ -133,7 +159,6 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
} }
} }
// 增加重试机制
cluster.RetryPolicy = &gocql.SimpleRetryPolicy{NumRetries: 3} cluster.RetryPolicy = &gocql.SimpleRetryPolicy{NumRetries: 3}
session, err := cluster.CreateSession() session, err := cluster.CreateSession()
@ -142,7 +167,6 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
} }
defer session.Close() defer session.Close()
// 使用更简单的查询测试连接
var version string var version string
if err := session.Query("SELECT peer FROM system.peers").Scan(&version); err != nil { if err := session.Query("SELECT peer FROM system.peers").Scan(&version); err != nil {
if err := session.Query("SELECT now() FROM system.local").Scan(&version); err != nil { if err := session.Query("SELECT now() FROM system.local").Scan(&version); err != nil {
@ -150,13 +174,5 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
} }
} }
result := fmt.Sprintf("Cassandra服务 %v:%v ", host, port)
if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else {
result += "无需认证即可访问"
}
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -16,8 +16,9 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试无认证访问...") Common.LogDebug("尝试无认证访问...")
// 首先测试无认证访问 // 首先测试无认证访问
@ -27,8 +28,22 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
} }
flag, err := ElasticConn(info, "", "") flag, err := ElasticConn(info, "", "")
if flag && err == nil { if flag && err == nil {
Common.LogSuccess(fmt.Sprintf("Elasticsearch服务 %v:%v 无需认证", successMsg := fmt.Sprintf("Elasticsearch服务 %s 无需认证", target)
info.Host, info.Ports)) Common.LogSuccess(successMsg)
// 保存无认证访问结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "elasticsearch",
"type": "unauthorized-access",
},
}
Common.SaveResult(result)
return err return err
} }
if err != nil && Common.CheckErrs(err) != nil { if err != nil && Common.CheckErrs(err) != nil {
@ -61,7 +76,6 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行连接尝试
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -78,36 +92,49 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
Common.LogSuccess(fmt.Sprintf("Elasticsearch服务 %v:%v 爆破成功 用户名: %v 密码: %v", successMsg := fmt.Sprintf("Elasticsearch服务 %s 爆破成功 用户名: %v 密码: %v",
info.Host, info.Ports, user, pass)) target, user, pass)
Common.LogSuccess(successMsg)
// 保存弱密码结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "elasticsearch",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Elasticsearch服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err) target, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break
break // 如果不需要重试,跳出重试循环
} }
} }
} }
@ -121,7 +148,6 @@ func ElasticConn(info *Common.HostInfo, user string, pass string) (bool, error)
host, port := info.Host, info.Ports host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
// 构造请求客户端
client := &http.Client{ client := &http.Client{
Timeout: timeout, Timeout: timeout,
Transport: &http.Transport{ Transport: &http.Transport{
@ -129,39 +155,22 @@ func ElasticConn(info *Common.HostInfo, user string, pass string) (bool, error)
}, },
} }
// 构造基础URL
baseURL := fmt.Sprintf("http://%s:%s", host, port) baseURL := fmt.Sprintf("http://%s:%s", host, port)
// 创建请求
req, err := http.NewRequest("GET", baseURL+"/_cat/indices", nil) req, err := http.NewRequest("GET", baseURL+"/_cat/indices", nil)
if err != nil { if err != nil {
return false, err return false, err
} }
// 如果提供了认证信息,添加Basic认证头
if user != "" || pass != "" { if user != "" || pass != "" {
auth := base64.StdEncoding.EncodeToString([]byte(user + ":" + pass)) auth := base64.StdEncoding.EncodeToString([]byte(user + ":" + pass))
req.Header.Add("Authorization", "Basic "+auth) req.Header.Add("Authorization", "Basic "+auth)
} }
// 发送请求
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
return false, err return false, err
} }
defer resp.Body.Close() defer resp.Body.Close()
// 检查响应状态 return resp.StatusCode == 200, nil
if resp.StatusCode == 200 {
result := fmt.Sprintf("Elasticsearch服务 %v:%v ", host, port)
if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else {
result += "无需认证即可访问"
}
Common.LogSuccess(result)
return true, nil
}
return false, fmt.Errorf("认证失败")
} }

View File

@ -14,18 +14,36 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试匿名登录...") Common.LogDebug("尝试匿名登录...")
// 尝试匿名登录 // 尝试匿名登录
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
flag, err := FtpConn(info, "anonymous", "") success, dirs, err := FtpConn(info, "anonymous", "")
if flag && err == nil { if success && err == nil {
Common.LogSuccess("匿名登录成功!") Common.LogSuccess("匿名登录成功!")
// 保存匿名登录结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "ftp",
"username": "anonymous",
"password": "",
"type": "anonymous-login",
"directories": dirs,
},
}
Common.SaveResult(result)
return nil return nil
} }
errlog := fmt.Sprintf("ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err) errlog := fmt.Sprintf("ftp %s %v", target, err)
Common.LogError(errlog) Common.LogError(errlog)
break break
} }
@ -37,7 +55,7 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
tried := 0 tried := 0
total := totalUsers * totalPass total := totalUsers * totalPass
// 遍历所有用户名密码组合 // 遍历用户名密码组合
for _, user := range Common.Userdict["ftp"] { for _, user := range Common.Userdict["ftp"] {
for _, pass := range Common.Passwords { for _, pass := range Common.Passwords {
tried++ tried++
@ -52,30 +70,46 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行FTP连接
done := make(chan struct { done := make(chan struct {
success bool success bool
dirs []string
err error err error
}, 1) }, 1)
go func(user, pass string) { go func(user, pass string) {
success, err := FtpConn(info, user, pass) success, dirs, err := FtpConn(info, user, pass)
select { select {
case done <- struct { case done <- struct {
success bool success bool
dirs []string
err error err error
}{success, err}: }{success, dirs, err}:
default: default:
} }
}(user, pass) }(user, pass)
// 等待结果或超时
select { select {
case result := <-done: case result := <-done:
if result.success && result.err == nil { if result.success && result.err == nil {
successLog := fmt.Sprintf("FTP %v:%v %v %v", successLog := fmt.Sprintf("FTP服务 %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
info.Host, info.Ports, user, pass)
Common.LogSuccess(successLog) Common.LogSuccess(successLog)
// 保存爆破成功结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "ftp",
"username": user,
"password": pass,
"type": "weak-password",
"directories": result.dirs,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
lastErr = result.err lastErr = result.err
@ -83,18 +117,16 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
lastErr = fmt.Errorf("连接超时") lastErr = fmt.Errorf("连接超时")
} }
// 处理错误情况 // 错误处理
if lastErr != nil { if lastErr != nil {
errlog := fmt.Sprintf("ftp %v:%v %v %v %v", errlog := fmt.Sprintf("FTP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, lastErr) target, user, pass, lastErr)
Common.LogError(errlog) Common.LogError(errlog)
// 如果是密码错误,直接尝试下一个组合
if strings.Contains(lastErr.Error(), "Login incorrect") { if strings.Contains(lastErr.Error(), "Login incorrect") {
break break
} }
// 如果是连接数限制,等待后重试
if strings.Contains(lastErr.Error(), "too many connections") { if strings.Contains(lastErr.Error(), "too many connections") {
Common.LogDebug("连接数过多等待5秒...") Common.LogDebug("连接数过多等待5秒...")
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
@ -112,39 +144,45 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
} }
// FtpConn 建立FTP连接并尝试登录 // FtpConn 建立FTP连接并尝试登录
func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err error) { func FtpConn(info *Common.HostInfo, user string, pass string) (success bool, directories []string, err error) {
Host, Port, Username, Password := info.Host, info.Ports, user, pass Host, Port := info.Host, info.Ports
// 建立FTP连接 // 建立FTP连接
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(Common.Timeout)*time.Second) conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(Common.Timeout)*time.Second)
if err != nil { if err != nil {
return false, err return false, nil, err
} }
// 确保连接被关闭
defer func() { defer func() {
if conn != nil { if conn != nil {
conn.Quit() // 发送QUIT命令关闭连接 conn.Quit()
} }
}() }()
// 尝试登录 // 尝试登录
if err = conn.Login(Username, Password); err != nil { if err = conn.Login(user, pass); err != nil {
return false, err return false, nil, err
} }
// 登录成功,获取目录信息 // 获取目录信息
result := fmt.Sprintf("ftp %v:%v:%v %v", Host, Port, Username, Password)
dirs, err := conn.List("") dirs, err := conn.List("")
if err == nil && len(dirs) > 0 { if err == nil && len(dirs) > 0 {
// 最多显示前6个目录 directories = make([]string, 0, min(6, len(dirs)))
for i := 0; i < len(dirs) && i < 6; i++ { for i := 0; i < len(dirs) && i < 6; i++ {
name := dirs[i].Name name := dirs[i].Name
if len(name) > 50 { if len(name) > 50 {
name = name[:50] name = name[:50]
} }
result += "\n [->]" + name directories = append(directories, name)
} }
} }
return true, nil return true, directories, nil
}
// min 返回两个整数中的较小值
func min(a, b int) int {
if a < b {
return a
}
return b
} }

View File

@ -148,15 +148,7 @@ func read(text []byte, host string) error {
name = "" name = ""
} }
// 构建基础结果 // 用于收集地址信息
result := fmt.Sprintf("NetInfo 扫描结果")
result += fmt.Sprintf("\n目标主机: %s", host)
if name != "" {
result += fmt.Sprintf("\n主机名: %s", name)
}
result += "\n发现的网络接口:"
// 用于分类存储地址
var ipv4Addrs []string var ipv4Addrs []string
var ipv6Addrs []string var ipv6Addrs []string
seenAddresses := make(map[string]bool) seenAddresses := make(map[string]bool)
@ -184,7 +176,6 @@ func read(text []byte, host string) error {
if addr != "" && !seenAddresses[addr] { if addr != "" && !seenAddresses[addr] {
seenAddresses[addr] = true seenAddresses[addr] = true
// 分类IPv4和IPv6地址
if strings.Contains(addr, ":") { if strings.Contains(addr, ":") {
ipv6Addrs = append(ipv6Addrs, addr) ipv6Addrs = append(ipv6Addrs, addr)
} else if net.ParseIP(addr) != nil { } else if net.ParseIP(addr) != nil {
@ -193,22 +184,46 @@ func read(text []byte, host string) error {
} }
} }
// 输出IPv4地址 // 构建详细信息
details := map[string]interface{}{
"hostname": name,
"ipv4": ipv4Addrs,
"ipv6": ipv6Addrs,
}
// 保存扫描结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.SERVICE,
Target: host,
Status: "identified",
Details: details,
}
Common.SaveResult(result)
// 构建控制台输出
var output strings.Builder
output.WriteString("NetInfo 扫描结果")
output.WriteString(fmt.Sprintf("\n目标主机: %s", host))
if name != "" {
output.WriteString(fmt.Sprintf("\n主机名: %s", name))
}
output.WriteString("\n发现的网络接口:")
if len(ipv4Addrs) > 0 { if len(ipv4Addrs) > 0 {
result += "\n IPv4地址:" output.WriteString("\n IPv4地址:")
for _, addr := range ipv4Addrs { for _, addr := range ipv4Addrs {
result += fmt.Sprintf("\n └─ %s", addr) output.WriteString(fmt.Sprintf("\n └─ %s", addr))
} }
} }
// 输出IPv6地址
if len(ipv6Addrs) > 0 { if len(ipv6Addrs) > 0 {
result += "\n IPv6地址:" output.WriteString("\n IPv6地址:")
for _, addr := range ipv6Addrs { for _, addr := range ipv6Addrs {
result += fmt.Sprintf("\n └─ %s", addr) output.WriteString(fmt.Sprintf("\n └─ %s", addr))
} }
} }
Common.LogSuccess(result) Common.LogSuccess(output.String())
return nil return nil
} }

View File

@ -11,14 +11,16 @@ import (
"time" "time"
) )
// IMAPScan 主扫描函数
func IMAPScan(info *Common.HostInfo) (tmperr error) { func IMAPScan(info *Common.HostInfo) (tmperr error) {
if Common.DisableBrute { if Common.DisableBrute {
return return
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["imap"]) totalUsers := len(Common.Userdict["imap"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -26,20 +28,17 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
tried := 0 tried := 0
total := totalUsers * totalPass total := totalUsers * totalPass
// 遍历所有用户名密码组合
for _, user := range Common.Userdict["imap"] { for _, user := range Common.Userdict["imap"] {
for _, pass := range Common.Passwords { for _, pass := range Common.Passwords {
tried++ tried++
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass)) Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行IMAP连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -56,23 +55,38 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success {
successMsg := fmt.Sprintf("IMAP服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass)
Common.LogSuccess(successMsg)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "imap",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errMsg := fmt.Sprintf("IMAP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err) Common.LogError(errMsg)
Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
@ -90,23 +104,22 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
return tmperr return tmperr
} }
// IMAPConn 连接测试函数
func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) { func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
host, port := info.Host, info.Ports host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
addr := fmt.Sprintf("%s:%s", host, port) addr := fmt.Sprintf("%s:%s", host, port)
// 首先尝试普通连接 // 尝试普通连接
Common.LogDebug(fmt.Sprintf("尝试普通连接: %s", addr))
conn, err := net.DialTimeout("tcp", addr, timeout) conn, err := net.DialTimeout("tcp", addr, timeout)
if err == nil { if err == nil {
if flag, err := tryIMAPAuth(conn, host, port, user, pass, timeout); err == nil { if flag, err := tryIMAPAuth(conn, user, pass, timeout); err == nil {
return flag, nil return flag, nil
} }
conn.Close() conn.Close()
} }
// 如果普通连接失败尝试TLS连接 // 尝试TLS连接
Common.LogDebug(fmt.Sprintf("尝试TLS连接: %s", addr))
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
InsecureSkipVerify: true, InsecureSkipVerify: true,
} }
@ -116,10 +129,11 @@ func IMAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
defer conn.Close() defer conn.Close()
return tryIMAPAuth(conn, host, port, user, pass, timeout) return tryIMAPAuth(conn, user, pass, timeout)
} }
func tryIMAPAuth(conn net.Conn, host string, port string, user string, pass string, timeout time.Duration) (bool, error) { // tryIMAPAuth 尝试IMAP认证
func tryIMAPAuth(conn net.Conn, user string, pass string, timeout time.Duration) (bool, error) {
conn.SetDeadline(time.Now().Add(timeout)) conn.SetDeadline(time.Now().Add(timeout))
reader := bufio.NewReader(conn) reader := bufio.NewReader(conn)
@ -145,9 +159,6 @@ func tryIMAPAuth(conn net.Conn, host string, port string, user string, pass stri
} }
if strings.Contains(response, "a001 OK") { if strings.Contains(response, "a001 OK") {
result := fmt.Sprintf("IMAP服务 %v:%v 爆破成功 用户名: %v 密码: %v",
host, port, user, pass)
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -14,9 +14,10 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
// 首先测试无认证访问 // 试无认证访问
Common.LogDebug("尝试无认证访问...") Common.LogDebug("尝试无认证访问...")
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
@ -24,6 +25,20 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
} }
flag, err := KafkaConn(info, "", "") flag, err := KafkaConn(info, "", "")
if flag && err == nil { if flag && err == nil {
// 保存无认证访问结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "kafka",
"type": "unauthorized-access",
},
}
Common.SaveResult(result)
Common.LogSuccess(fmt.Sprintf("Kafka服务 %s 无需认证即可访问", target))
return nil return nil
} }
if err != nil && Common.CheckErrs(err) != nil { if err != nil && Common.CheckErrs(err) != nil {
@ -49,13 +64,11 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass)) Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行Kafka连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -72,33 +85,44 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
// 保存爆破成功结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "kafka",
"type": "weak-password",
"username": user,
"password": pass,
},
}
Common.SaveResult(vulnResult)
Common.LogSuccess(fmt.Sprintf("Kafka服务 %s 爆破成功 用户名: %s 密码: %s", target, user, pass))
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", Common.LogError(fmt.Sprintf("Kafka服务 %s 尝试失败 用户名: %s 密码: %s 错误: %v",
info.Host, info.Ports, user, pass, err) target, user, pass, err))
Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }
@ -132,13 +156,6 @@ func KafkaConn(info *Common.HostInfo, user string, pass string) (bool, error) {
consumer, err := sarama.NewConsumer(brokers, config) consumer, err := sarama.NewConsumer(brokers, config)
if err == nil { if err == nil {
defer consumer.Close() defer consumer.Close()
result := fmt.Sprintf("Kafka服务 %v:%v ", host, port)
if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else {
result += "无需认证即可访问"
}
Common.LogSuccess(result)
return true, nil return true, nil
} }
@ -146,13 +163,6 @@ func KafkaConn(info *Common.HostInfo, user string, pass string) (bool, error) {
client, err := sarama.NewClient(brokers, config) client, err := sarama.NewClient(brokers, config)
if err == nil { if err == nil {
defer client.Close() defer client.Close()
result := fmt.Sprintf("Kafka服务 %v:%v ", host, port)
if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else {
result += "无需认证即可访问"
}
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -14,13 +14,28 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试匿名访问...") Common.LogDebug("尝试匿名访问...")
// 首先尝试匿名访问 // 首先尝试匿名访问
flag, err := LDAPConn(info, "", "") flag, err := LDAPConn(info, "", "")
if flag && err == nil { if flag && err == nil {
// 记录匿名访问成功
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "ldap",
"type": "anonymous-access",
},
}
Common.SaveResult(result)
Common.LogSuccess(fmt.Sprintf("LDAP服务 %s 匿名访问成功", target))
return err return err
} }
@ -44,7 +59,6 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行LDAP连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -61,30 +75,42 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
// 记录成功爆破的凭据
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "ldap",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
Common.LogSuccess(fmt.Sprintf("LDAP服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass))
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("LDAP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break break
@ -97,11 +123,8 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
} }
func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) { func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
host, port := info.Host, info.Ports address := fmt.Sprintf("%s:%s", info.Host, info.Ports)
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
address := fmt.Sprintf("%s:%s", host, port)
Common.LogDebug(fmt.Sprintf("尝试连接: %s", address))
// 配置LDAP连接 // 配置LDAP连接
l, err := ldap.Dial("tcp", address) l, err := ldap.Dial("tcp", address)
@ -115,11 +138,9 @@ func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
// 尝试绑定 // 尝试绑定
if user != "" { if user != "" {
// 构造DN
bindDN := fmt.Sprintf("cn=%s,dc=example,dc=com", user) bindDN := fmt.Sprintf("cn=%s,dc=example,dc=com", user)
err = l.Bind(bindDN, pass) err = l.Bind(bindDN, pass)
} else { } else {
// 匿名绑定
err = l.UnauthenticatedBind("") err = l.UnauthenticatedBind("")
} }
@ -141,14 +162,5 @@ func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
return false, err return false, err
} }
// 记录成功结果
result := fmt.Sprintf("LDAP服务 %v:%v ", host, port)
if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else {
result += "匿名访问成功"
}
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -203,15 +203,31 @@ func MS17010Scan(info *Common.HostInfo) error {
return fmt.Errorf("管道响应不完整") return fmt.Errorf("管道响应不完整")
} }
// 漏洞检测 // 漏洞检测部分添加 Output
if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 { if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
// 构造基本详情
details := map[string]interface{}{
"port": "445",
"vulnerability": "MS17-010",
}
if os != "" { if os != "" {
details["os"] = os
Common.LogSuccess(fmt.Sprintf("发现漏洞 %s [%s] MS17-010", ip, os)) Common.LogSuccess(fmt.Sprintf("发现漏洞 %s [%s] MS17-010", ip, os))
} else { } else {
Common.LogSuccess(fmt.Sprintf("发现漏洞 %s MS17-010", ip)) Common.LogSuccess(fmt.Sprintf("发现漏洞 %s MS17-010", ip))
} }
// DOUBLEPULSAR后门检测 // 保存 MS17-010 漏洞结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: ip,
Status: "vulnerable",
Details: details,
}
Common.SaveResult(result)
// DOUBLEPULSAR 后门检测
trans2SessionSetupRequest[28] = treeID[0] trans2SessionSetupRequest[28] = treeID[0]
trans2SessionSetupRequest[29] = treeID[1] trans2SessionSetupRequest[29] = treeID[1]
trans2SessionSetupRequest[32] = userID[0] trans2SessionSetupRequest[32] = userID[0]
@ -230,14 +246,42 @@ func MS17010Scan(info *Common.HostInfo) error {
if reply[34] == 0x51 { if reply[34] == 0x51 {
Common.LogSuccess(fmt.Sprintf("发现后门 %s DOUBLEPULSAR", ip)) Common.LogSuccess(fmt.Sprintf("发现后门 %s DOUBLEPULSAR", ip))
// 保存 DOUBLEPULSAR 后门结果
backdoorResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: ip,
Status: "backdoor",
Details: map[string]interface{}{
"port": "445",
"type": "DOUBLEPULSAR",
"os": os,
},
}
Common.SaveResult(backdoorResult)
} }
// Shellcode利用 // Shellcode 利用部分保持不变
if Common.Shellcode != "" { if Common.Shellcode != "" {
defer MS17010EXP(info) defer MS17010EXP(info)
} }
} else if os != "" { } else if os != "" {
Common.LogInfo(fmt.Sprintf("系统信息 %s [%s]", ip, os)) Common.LogInfo(fmt.Sprintf("系统信息 %s [%s]", ip, os))
// 保存系统信息
sysResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.SERVICE,
Target: ip,
Status: "identified",
Details: map[string]interface{}{
"port": "445",
"service": "smb",
"os": os,
},
}
Common.SaveResult(sysResult)
} }
return nil return nil

View File

@ -16,8 +16,9 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["mssql"]) totalUsers := len(Common.Userdict["mssql"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -61,8 +62,24 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
Common.LogSuccess(fmt.Sprintf("MSSQL %v:%v %v %v", successMsg := fmt.Sprintf("MSSQL %s %v %v", target, user, pass)
info.Host, info.Ports, user, pass)) Common.LogSuccess(successMsg)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "mssql",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
@ -70,20 +87,18 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("MSSQL %v:%v %v %v %v", errlog := fmt.Sprintf("MSSQL %s %v %v %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }
@ -120,8 +135,5 @@ func MssqlConn(info *Common.HostInfo, user string, pass string) (bool, error) {
return false, err return false, err
} }
// 连接成功
result := fmt.Sprintf("MSSQL %v:%v:%v %v", host, port, username, password)
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -33,15 +33,27 @@ func MemcachedScan(info *Common.HostInfo) error {
rev := make([]byte, 1024) rev := make([]byte, 1024)
n, err := client.Read(rev) n, err := client.Read(rev)
if err != nil { if err != nil {
errlog := fmt.Sprintf("Memcached %v:%v %v", info.Host, info.Ports, err) Common.LogError(fmt.Sprintf("Memcached %v:%v %v", info.Host, info.Ports, err))
Common.LogError(errlog)
return err return err
} }
// 检查响应内容 // 检查响应内容
if strings.Contains(string(rev[:n]), "STAT") { if strings.Contains(string(rev[:n]), "STAT") {
result := fmt.Sprintf("Memcached %s 未授权访问", realhost) // 保存结果
Common.LogSuccess(result) result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "memcached",
"type": "unauthorized-access",
"description": "Memcached unauthorized access",
},
}
Common.SaveResult(result)
Common.LogSuccess(fmt.Sprintf("Memcached %s 未授权访问", realhost))
} }
return nil return nil

View File

@ -41,14 +41,30 @@ func ModbusScan(info *Common.HostInfo) error {
// 验证响应 // 验证响应
if isValidModbusResponse(response[:n]) { if isValidModbusResponse(response[:n]) {
result := fmt.Sprintf("Modbus服务 %v:%v 无认证访问", host, port) // 获取设备信息
Common.LogSuccess(result)
// 尝试读取更多设备信息
deviceInfo := parseModbusResponse(response[:n]) deviceInfo := parseModbusResponse(response[:n])
// 保存扫描结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": port,
"service": "modbus",
"type": "unauthorized-access",
"device_id": deviceInfo,
},
}
Common.SaveResult(result)
// 控制台输出
Common.LogSuccess(fmt.Sprintf("Modbus服务 %v:%v 无认证访问", host, port))
if deviceInfo != "" { if deviceInfo != "" {
Common.LogSuccess(fmt.Sprintf("设备信息: %s", deviceInfo)) Common.LogSuccess(fmt.Sprintf("设备信息: %s", deviceInfo))
} }
return nil return nil
} }

View File

@ -13,17 +13,37 @@ func MongodbScan(info *Common.HostInfo) error {
return nil return nil
} }
_, err := MongodbUnauth(info) target := fmt.Sprintf("%s:%v", info.Host, info.Ports)
isUnauth, err := MongodbUnauth(info)
if err != nil { if err != nil {
errlog := fmt.Sprintf("MongoDB %v:%v %v", info.Host, info.Ports, err) errlog := fmt.Sprintf("MongoDB %v %v", target, err)
Common.LogError(errlog) Common.LogError(errlog)
} else if isUnauth {
// 记录控制台输出
Common.LogSuccess(fmt.Sprintf("MongoDB %v 未授权访问", target))
// 保存未授权访问结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "mongodb",
"type": "unauthorized-access",
"protocol": "mongodb",
},
} }
Common.SaveResult(result)
}
return err return err
} }
// MongodbUnauth 检测MongoDB未授权访问 // MongodbUnauth 检测MongoDB未授权访问
func MongodbUnauth(info *Common.HostInfo) (bool, error) { func MongodbUnauth(info *Common.HostInfo) (bool, error) {
// MongoDB查询数据包
msgPacket := createOpMsgPacket() msgPacket := createOpMsgPacket()
queryPacket := createOpQueryPacket() queryPacket := createOpQueryPacket()
@ -41,8 +61,6 @@ func MongodbUnauth(info *Common.HostInfo) (bool, error) {
// 检查响应结果 // 检查响应结果
if strings.Contains(reply, "totalLinesWritten") { if strings.Contains(reply, "totalLinesWritten") {
result := fmt.Sprintf("MongoDB %v 未授权访问", realhost)
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -16,8 +16,9 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["mysql"]) totalUsers := len(Common.Userdict["mysql"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -38,7 +39,6 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行MySQL连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -55,33 +55,43 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
successLog := fmt.Sprintf("MySQL %v:%v %v %v", successMsg := fmt.Sprintf("MySQL %s %v %v", target, user, pass)
info.Host, info.Ports, user, pass) Common.LogSuccess(successMsg)
Common.LogSuccess(successLog)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "mysql",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("MySQL %v:%v %v %v %v", errMsg := fmt.Sprintf("MySQL %s %v %v %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err) Common.LogError(errMsg)
Common.LogError(errlog)
// 特殊处理认证失败的情况
if strings.Contains(err.Error(), "Access denied") { if strings.Contains(err.Error(), "Access denied") {
break // 跳出重试循环,继续下一个密码 break // 认证失败,尝试下一个密码
} }
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
tmperr = err tmperr = err
@ -89,9 +99,9 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
continue continue
} }
} }
continue // 继续重试 continue
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }

View File

@ -14,8 +14,9 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
// 首先测试无认证访问和默认凭证 // 首先测试无认证访问和默认凭证
initialChecks := []struct { initialChecks := []struct {
@ -31,6 +32,44 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("尝试: %s:%s", check.user, check.pass)) Common.LogDebug(fmt.Sprintf("尝试: %s:%s", check.user, check.pass))
flag, err := Neo4jConn(info, check.user, check.pass) flag, err := Neo4jConn(info, check.user, check.pass)
if flag && err == nil { if flag && err == nil {
var msg string
if check.user == "" {
msg = fmt.Sprintf("Neo4j服务 %s 无需认证即可访问", target)
Common.LogSuccess(msg)
// 保存结果 - 无认证访问
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "neo4j",
"type": "unauthorized-access",
},
}
Common.SaveResult(result)
} else {
msg = fmt.Sprintf("Neo4j服务 %s 默认凭证可用 用户名: %s 密码: %s", target, check.user, check.pass)
Common.LogSuccess(msg)
// 保存结果 - 默认凭证
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "neo4j",
"type": "default-credentials",
"username": check.user,
"password": check.pass,
},
}
Common.SaveResult(result)
}
return err return err
} }
} }
@ -55,7 +94,6 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行Neo4j连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -72,33 +110,47 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
msg := fmt.Sprintf("Neo4j服务 %s 爆破成功 用户名: %s 密码: %s", target, user, pass)
Common.LogSuccess(msg)
// 保存结果 - 成功爆破
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "neo4j",
"type": "weak-password",
"username": user,
"password": pass,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Neo4j服务 %s 尝试失败 用户名: %s 密码: %s 错误: %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }
@ -143,13 +195,5 @@ func Neo4jConn(info *Common.HostInfo, user string, pass string) (bool, error) {
return false, err return false, err
} }
// 连接成功
result := fmt.Sprintf("Neo4j服务 %v:%v ", host, port)
if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else {
result += "无需认证即可访问"
}
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -20,6 +20,47 @@ func NetBIOS(info *Common.HostInfo) error {
if len(output) > 0 { if len(output) > 0 {
result := fmt.Sprintf("NetBios %-15s %s", info.Host, output) result := fmt.Sprintf("NetBios %-15s %s", info.Host, output)
Common.LogSuccess(result) Common.LogSuccess(result)
// 保存结果
details := map[string]interface{}{
"port": info.Ports,
}
// 添加有效的 NetBIOS 信息
if netbios.ComputerName != "" {
details["computer_name"] = netbios.ComputerName
}
if netbios.DomainName != "" {
details["domain_name"] = netbios.DomainName
}
if netbios.NetDomainName != "" {
details["netbios_domain"] = netbios.NetDomainName
}
if netbios.NetComputerName != "" {
details["netbios_computer"] = netbios.NetComputerName
}
if netbios.WorkstationService != "" {
details["workstation_service"] = netbios.WorkstationService
}
if netbios.ServerService != "" {
details["server_service"] = netbios.ServerService
}
if netbios.DomainControllers != "" {
details["domain_controllers"] = netbios.DomainControllers
}
if netbios.OsVersion != "" {
details["os_version"] = netbios.OsVersion
}
scanResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.SERVICE,
Target: info.Host,
Status: "identified",
Details: details,
}
Common.SaveResult(scanResult)
return nil return nil
} }
return errNetBIOS return errNetBIOS

View File

@ -15,8 +15,9 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["oracle"]) totalUsers := len(Common.Userdict["oracle"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -60,9 +61,24 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
successLog := fmt.Sprintf("Oracle %v:%v %v %v", successMsg := fmt.Sprintf("Oracle %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
info.Host, info.Ports, user, pass) Common.LogSuccess(successMsg)
Common.LogSuccess(successLog)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "oracle",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
@ -71,19 +87,17 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("Oracle %v:%v %v %v %v", errMsg := fmt.Sprintf("Oracle %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err) Common.LogError(errMsg)
Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }
@ -118,8 +132,5 @@ func OracleConn(info *Common.HostInfo, user string, pass string) (bool, error) {
return false, err return false, err
} }
// 连接成功
result := fmt.Sprintf("Oracle %v:%v:%v %v", host, port, username, password)
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -16,8 +16,9 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["pop3"]) totalUsers := len(Common.Userdict["pop3"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -38,53 +39,70 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行POP3连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
isTLS bool
}, 1) }, 1)
go func(user, pass string) { go func(user, pass string) {
success, err := POP3Conn(info, user, pass) success, isTLS, err := POP3Conn(info, user, pass)
select { select {
case done <- struct { case done <- struct {
success bool success bool
err error err error
}{success, err}: isTLS bool
}{success, err, isTLS}:
default: default:
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
successLog := fmt.Sprintf("POP3服务 %v:%v 用户名: %v 密码: %v", successMsg := fmt.Sprintf("POP3服务 %s 用户名: %v 密码: %v", target, user, pass)
info.Host, info.Ports, user, pass) if result.isTLS {
Common.LogSuccess(successLog) successMsg += " (TLS)"
}
Common.LogSuccess(successMsg)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "pop3",
"username": user,
"password": pass,
"type": "weak-password",
"tls": result.isTLS,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errMsg := fmt.Sprintf("POP3服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err) target, user, pass, err)
Common.LogError(errlog) Common.LogError(errMsg)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }
@ -93,16 +111,15 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
return tmperr return tmperr
} }
func POP3Conn(info *Common.HostInfo, user string, pass string) (bool, error) { func POP3Conn(info *Common.HostInfo, user string, pass string) (success bool, isTLS bool, err error) {
host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
addr := fmt.Sprintf("%s:%s", host, port) addr := fmt.Sprintf("%s:%s", info.Host, info.Ports)
// 首先尝试普通连接 // 首先尝试普通连接
conn, err := net.DialTimeout("tcp", addr, timeout) conn, err := net.DialTimeout("tcp", addr, timeout)
if err == nil { if err == nil {
if flag, err := tryPOP3Auth(conn, host, port, user, pass, timeout, false); err == nil { if flag, err := tryPOP3Auth(conn, user, pass, timeout); err == nil {
return flag, nil return flag, false, nil
} }
conn.Close() conn.Close()
} }
@ -113,14 +130,15 @@ func POP3Conn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
conn, err = tls.DialWithDialer(&net.Dialer{Timeout: timeout}, "tcp", addr, tlsConfig) conn, err = tls.DialWithDialer(&net.Dialer{Timeout: timeout}, "tcp", addr, tlsConfig)
if err != nil { if err != nil {
return false, fmt.Errorf("连接失败: %v", err) return false, false, fmt.Errorf("连接失败: %v", err)
} }
defer conn.Close() defer conn.Close()
return tryPOP3Auth(conn, host, port, user, pass, timeout, true) success, err = tryPOP3Auth(conn, user, pass, timeout)
return success, true, err
} }
func tryPOP3Auth(conn net.Conn, host string, port string, user string, pass string, timeout time.Duration, isTLS bool) (bool, error) { func tryPOP3Auth(conn net.Conn, user string, pass string, timeout time.Duration) (bool, error) {
reader := bufio.NewReader(conn) reader := bufio.NewReader(conn)
conn.SetDeadline(time.Now().Add(timeout)) conn.SetDeadline(time.Now().Add(timeout))
@ -162,11 +180,6 @@ func tryPOP3Auth(conn net.Conn, host string, port string, user string, pass stri
} }
if strings.Contains(response, "+OK") { if strings.Contains(response, "+OK") {
result := fmt.Sprintf("POP3服务 %v:%v 爆破成功 用户名: %v 密码: %v", host, port, user, pass)
if isTLS {
result += " (TLS)"
}
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -15,9 +15,10 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
return return
} }
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["postgresql"]) totalUsers := len(Common.Userdict["postgresql"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -25,20 +26,17 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
tried := 0 tried := 0
total := totalUsers * totalPass total := totalUsers * totalPass
// 遍历所有用户名密码组合
for _, user := range Common.Userdict["postgresql"] { for _, user := range Common.Userdict["postgresql"] {
for _, pass := range Common.Passwords { for _, pass := range Common.Passwords {
tried++ tried++
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass)) Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行PostgreSQL连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -55,36 +53,47 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
successLog := fmt.Sprintf("PostgreSQL %v:%v %v %v", successMsg := fmt.Sprintf("PostgreSQL服务 %s 成功爆破 用户名: %v 密码: %v", target, user, pass)
info.Host, info.Ports, user, pass) Common.LogSuccess(successMsg)
Common.LogSuccess(successLog)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "postgresql",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("PostgreSQL %v:%v %v %v %v", errMsg := fmt.Sprintf("PostgreSQL服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err) Common.LogError(errMsg)
Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }
@ -95,13 +104,12 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
// PostgresConn 尝试PostgreSQL连接 // PostgresConn 尝试PostgreSQL连接
func PostgresConn(info *Common.HostInfo, user string, pass string) (bool, error) { func PostgresConn(info *Common.HostInfo, user string, pass string) (bool, error) {
host, port, username, password := info.Host, info.Ports, user, pass
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
// 构造连接字符串 // 构造连接字符串
connStr := fmt.Sprintf( connStr := fmt.Sprintf(
"postgres://%v:%v@%v:%v/postgres?sslmode=disable", "postgres://%v:%v@%v:%v/postgres?sslmode=disable",
username, password, host, port, user, pass, info.Host, info.Ports,
) )
// 建立数据库连接 // 建立数据库连接
@ -119,8 +127,5 @@ func PostgresConn(info *Common.HostInfo, user string, pass string) (bool, error)
return false, err return false, err
} }
// 连接成功
result := fmt.Sprintf("PostgreSQL %v:%v:%v %v", host, port, username, password)
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -40,6 +40,7 @@ func RdpScan(info *Common.HostInfo) (tmperr error) {
port, _ := strconv.Atoi(info.Ports) port, _ := strconv.Atoi(info.Ports)
total := len(Common.Userdict["rdp"]) * len(Common.Passwords) total := len(Common.Userdict["rdp"]) * len(Common.Passwords)
num := 0 num := 0
target := fmt.Sprintf("%v:%v", info.Host, port)
// 遍历用户名密码组合 // 遍历用户名密码组合
for _, user := range Common.Userdict["rdp"] { for _, user := range Common.Userdict["rdp"] {
@ -54,16 +55,39 @@ func RdpScan(info *Common.HostInfo) (tmperr error) {
// 连接成功 // 连接成功
var result string var result string
if Common.Domain != "" { if Common.Domain != "" {
result = fmt.Sprintf("RDP %v:%v:%v\\%v %v", info.Host, port, Common.Domain, user, pass) result = fmt.Sprintf("RDP %v Domain: %v\\%v Password: %v", target, Common.Domain, user, pass)
} else { } else {
result = fmt.Sprintf("RDP %v:%v:%v %v", info.Host, port, user, pass) result = fmt.Sprintf("RDP %v Username: %v Password: %v", target, user, pass)
} }
Common.LogSuccess(result) Common.LogSuccess(result)
// 保存结果
details := map[string]interface{}{
"port": port,
"service": "rdp",
"username": user,
"password": pass,
"type": "weak-password",
}
if Common.Domain != "" {
details["domain"] = Common.Domain
}
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: details,
}
Common.SaveResult(vulnResult)
return nil return nil
} }
// 连接失败 // 连接失败
errlog := fmt.Sprintf("(%v/%v) RDP %v:%v %v %v %v", num, total, info.Host, port, user, pass, err) errlog := fmt.Sprintf("(%v/%v) RDP %v Username: %v Password: %v Error: %v",
num, total, target, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
} }
} }

View File

@ -16,8 +16,9 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试默认账号 guest/guest") Common.LogDebug("尝试默认账号 guest/guest")
// 先测试默认账号 guest/guest // 先测试默认账号 guest/guest
@ -27,7 +28,6 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试默认账号: guest/guest", retryCount+1)) Common.LogDebug(fmt.Sprintf("第%d次重试默认账号: guest/guest", retryCount+1))
} }
// 执行RabbitMQ连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -44,15 +44,29 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
} }
}() }()
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
result := fmt.Sprintf("RabbitMQ服务 %v:%v 连接成功 用户名: %v 密码: %v", successMsg := fmt.Sprintf("RabbitMQ服务 %s 连接成功 用户名: %v 密码: %v", target, user, pass)
info.Host, info.Ports, user, pass) Common.LogSuccess(successMsg)
Common.LogSuccess(result)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "rabbitmq",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
@ -60,8 +74,8 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("RabbitMQ服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err) target, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
@ -74,7 +88,6 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
break break
} }
// 计算总尝试次数
totalUsers := len(Common.Userdict["rabbitmq"]) totalUsers := len(Common.Userdict["rabbitmq"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
total := totalUsers * totalPass total := totalUsers * totalPass
@ -89,13 +102,11 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass)) Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行RabbitMQ连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -112,15 +123,30 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
result := fmt.Sprintf("RabbitMQ服务 %v:%v 连接成功 用户名: %v 密码: %v", successMsg := fmt.Sprintf("RabbitMQ服务 %s 连接成功 用户名: %v 密码: %v",
info.Host, info.Ports, user, pass) target, user, pass)
Common.LogSuccess(result) Common.LogSuccess(successMsg)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "rabbitmq",
"username": user,
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
@ -128,8 +154,8 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("RabbitMQ服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err) target, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
@ -144,7 +170,7 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
} }
} }
Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried+1)) // +1 包含默认账号 Common.LogDebug(fmt.Sprintf("扫描完成,共尝试 %d 个组合", tried+1))
return tmperr return tmperr
} }
@ -172,8 +198,6 @@ func RabbitMQConn(info *Common.HostInfo, user string, pass string) (bool, error)
// 如果成功连接 // 如果成功连接
if conn != nil { if conn != nil {
result := fmt.Sprintf("RabbitMQ服务 %v:%v 爆破成功 用户名: %v 密码: %v", host, port, user, pass)
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -16,7 +16,6 @@ var (
dir string // Redis数据库目录 dir string // Redis数据库目录
) )
// RedisScan 执行Redis服务扫描
func RedisScan(info *Common.HostInfo) error { func RedisScan(info *Common.HostInfo) error {
Common.LogDebug(fmt.Sprintf("开始Redis扫描: %s:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始Redis扫描: %s:%v", info.Host, info.Ports))
starttime := time.Now().Unix() starttime := time.Now().Unix()
@ -25,6 +24,20 @@ func RedisScan(info *Common.HostInfo) error {
flag, err := RedisUnauth(info) flag, err := RedisUnauth(info)
if flag && err == nil { if flag && err == nil {
Common.LogSuccess(fmt.Sprintf("Redis无密码连接成功: %s:%v", info.Host, info.Ports)) Common.LogSuccess(fmt.Sprintf("Redis无密码连接成功: %s:%v", info.Host, info.Ports))
// 保存未授权访问结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "redis",
"type": "unauthorized",
},
}
Common.SaveResult(result)
return nil return nil
} }
@ -42,19 +55,15 @@ func RedisScan(info *Common.HostInfo) error {
return fmt.Errorf(errMsg) return fmt.Errorf(errMsg)
} }
// 替换密码模板
pass = strings.Replace(pass, "{user}", "redis", -1) pass = strings.Replace(pass, "{user}", "redis", -1)
Common.LogDebug(fmt.Sprintf("尝试密码: %s", pass)) Common.LogDebug(fmt.Sprintf("尝试密码: %s", pass))
// 密码重试逻辑
var lastErr error var lastErr error
for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ { for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
// 如果不是第一次重试,添加重试日志
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第 %d 次重试: %s", retryCount+1, pass)) Common.LogDebug(fmt.Sprintf("第 %d 次重试: %s", retryCount+1, pass))
} }
// 执行Redis连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -68,13 +77,27 @@ func RedisScan(info *Common.HostInfo) error {
}{success, err} }{success, err}
}() }()
// 等待结果或超时
var connErr error var connErr error
select { select {
case result := <-done: case result := <-done:
if result.success { if result.success {
Common.LogSuccess(fmt.Sprintf("Redis登录成功 %s:%v [%s]", Common.LogSuccess(fmt.Sprintf("Redis登录成功 %s:%v [%s]",
info.Host, info.Ports, pass)) info.Host, info.Ports, pass))
// 保存弱密码结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "redis",
"type": "weak-password",
"password": pass,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
connErr = result.err connErr = result.err
@ -82,27 +105,23 @@ func RedisScan(info *Common.HostInfo) error {
connErr = fmt.Errorf("连接超时") connErr = fmt.Errorf("连接超时")
} }
// 处理错误情况
if connErr != nil { if connErr != nil {
lastErr = connErr lastErr = connErr
errMsg := fmt.Sprintf("Redis尝试失败 %s:%v [%s] %v", errMsg := fmt.Sprintf("Redis尝试失败 %s:%v [%s] %v",
info.Host, info.Ports, pass, connErr) info.Host, info.Ports, pass, connErr)
Common.LogError(errMsg) Common.LogError(errMsg)
// 检查是否需要重试
if retryErr := Common.CheckErrs(connErr); retryErr != nil { if retryErr := Common.CheckErrs(connErr); retryErr != nil {
if retryCount == Common.MaxRetries-1 { if retryCount == Common.MaxRetries-1 {
Common.LogDebug(fmt.Sprintf("达到最大重试次数: %s", pass)) Common.LogDebug(fmt.Sprintf("达到最大重试次数: %s", pass))
break break
} }
continue // 继续重试 continue
} }
} }
break
}
break // 如果不需要重试,跳出重试循环
}
// 如果最后一次尝试遇到需要重试的错误,返回该错误
if lastErr != nil && Common.CheckErrs(lastErr) != nil { if lastErr != nil && Common.CheckErrs(lastErr) != nil {
Common.LogDebug(fmt.Sprintf("Redis扫描中断: %v", lastErr)) Common.LogDebug(fmt.Sprintf("Redis扫描中断: %v", lastErr))
return lastErr return lastErr

View File

@ -8,15 +8,15 @@ import (
"time" "time"
) )
// RsyncScan 执行 Rsync 服务扫描
func RsyncScan(info *Common.HostInfo) (tmperr error) { func RsyncScan(info *Common.HostInfo) (tmperr error) {
if Common.DisableBrute { if Common.DisableBrute {
return return
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试匿名访问...") Common.LogDebug("尝试匿名访问...")
// 首先测试匿名访问 // 首先测试匿名访问
@ -27,14 +27,26 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
flag, err := RsyncConn(info, "", "") flag, err := RsyncConn(info, "", "")
if flag && err == nil { if flag && err == nil {
Common.LogSuccess(fmt.Sprintf("Rsync服务 %v:%v 匿名访问成功", info.Host, info.Ports)) Common.LogSuccess(fmt.Sprintf("Rsync服务 %s 匿名访问成功", target))
// 保存匿名访问结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "rsync",
"type": "anonymous-access",
},
}
Common.SaveResult(result)
return err return err
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("Rsync服务 %v:%v 匿名访问失败: %v", info.Host, info.Ports, err) Common.LogError(fmt.Sprintf("Rsync服务 %s 匿名访问失败: %v", target, err))
Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
return err return err
@ -52,20 +64,17 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
tried := 0 tried := 0
total := totalUsers * totalPass total := totalUsers * totalPass
// 遍历所有用户名密码组合
for _, user := range Common.Userdict["rsync"] { for _, user := range Common.Userdict["rsync"] {
for _, pass := range Common.Passwords { for _, pass := range Common.Passwords {
tried++ tried++
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass)) Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试: %s:%s", tried, total, user, pass))
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行Rsync连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -82,37 +91,46 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success { if result.success {
successLog := fmt.Sprintf("Rsync服务 %v:%v 爆破成功 用户名: %v 密码: %v", Common.LogSuccess(fmt.Sprintf("Rsync服务 %s 爆破成功 用户名: %v 密码: %v",
info.Host, info.Ports, user, pass) target, user, pass))
Common.LogSuccess(successLog)
// 保存爆破成功结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "rsync",
"type": "weak-password",
"username": user,
"password": pass,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", Common.LogError(fmt.Sprintf("Rsync服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err) target, user, pass, err))
Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break
break // 如果不需要重试,跳出重试循环
} }
} }
} }

View File

@ -13,6 +13,8 @@ func SmbScan(info *Common.HostInfo) (tmperr error) {
return nil return nil
} }
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
// 遍历所有用户 // 遍历所有用户
for _, user := range Common.Userdict["smb"] { for _, user := range Common.Userdict["smb"] {
// 遍历该用户的所有密码 // 遍历该用户的所有密码
@ -21,19 +23,41 @@ func SmbScan(info *Common.HostInfo) (tmperr error) {
success, err := doWithTimeOut(info, user, pass) success, err := doWithTimeOut(info, user, pass)
if success { if success {
if Common.Domain != "" { // 构建结果消息
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s\\%s:%s", var successMsg string
info.Host, info.Ports, Common.Domain, user, pass)) details := map[string]interface{}{
} else { "port": info.Ports,
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s:%s", "service": "smb",
info.Host, info.Ports, user, pass)) "username": user,
"password": pass,
"type": "weak-password",
} }
if Common.Domain != "" {
successMsg = fmt.Sprintf("SMB认证成功 %s %s\\%s:%s", target, Common.Domain, user, pass)
details["domain"] = Common.Domain
} else {
successMsg = fmt.Sprintf("SMB认证成功 %s %s:%s", target, user, pass)
}
// 记录成功日志
Common.LogSuccess(successMsg)
// 保存结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: details,
}
Common.SaveResult(result)
return nil return nil
} }
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("SMB认证失败 %s:%s %s:%s %v", errMsg := fmt.Sprintf("SMB认证失败 %s %s:%s %v", target, user, pass, err)
info.Host, info.Ports, user, pass, err)) Common.LogError(errMsg)
// 等待失败日志打印完成 // 等待失败日志打印完成
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
@ -68,9 +92,6 @@ func SmblConn(info *Common.HostInfo, user string, pass string, signal chan struc
return false, fmt.Errorf("认证失败") return false, fmt.Errorf("认证失败")
} }
// 添加 debug 输出原始错误信息
Common.LogDebug(fmt.Sprintf("SMB original error: %v", err))
// 清理错误信息中的换行符和多余空格 // 清理错误信息中的换行符和多余空格
errMsg := strings.TrimSpace(strings.ReplaceAll(err.Error(), "\n", " ")) errMsg := strings.TrimSpace(strings.ReplaceAll(err.Error(), "\n", " "))
if strings.Contains(errMsg, "NT Status Error") { if strings.Contains(errMsg, "NT Status Error") {

View File

@ -145,21 +145,43 @@ func smbHashScan(info *Common.HostInfo) error {
// logSuccessfulAuth 记录成功的认证 // logSuccessfulAuth 记录成功的认证
func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) { func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
var result string credential := pass
if len(hash) > 0 {
credential = Common.HashValue
}
// 保存认证成功结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "success",
Details: map[string]interface{}{
"port": info.Ports,
"service": "smb2",
"username": user,
"domain": Common.Domain,
"type": "weak-auth",
"credential": credential,
"auth_type": map[bool]string{true: "hash", false: "password"}[len(hash) > 0],
},
}
Common.SaveResult(result)
// 控制台输出
var msg string
if Common.Domain != "" { if Common.Domain != "" {
result = fmt.Sprintf("SMB2认证成功 %s:%s %s\\%s", msg = fmt.Sprintf("SMB2认证成功 %s:%s %s\\%s", info.Host, info.Ports, Common.Domain, user)
info.Host, info.Ports, Common.Domain, user)
} else { } else {
result = fmt.Sprintf("SMB2认证成功 %s:%s %s", msg = fmt.Sprintf("SMB2认证成功 %s:%s %s", info.Host, info.Ports, user)
info.Host, info.Ports, user)
} }
if len(hash) > 0 { if len(hash) > 0 {
result += fmt.Sprintf(" Hash:%s", Common.HashValue) msg += fmt.Sprintf(" Hash:%s", Common.HashValue)
} else { } else {
result += fmt.Sprintf(" Pass:%s", pass) msg += fmt.Sprintf(" Pass:%s", pass)
} }
Common.LogSuccess(result) Common.LogSuccess(msg)
} }
// logFailedAuth 记录失败的认证 // logFailedAuth 记录失败的认证
@ -241,21 +263,42 @@ func Smb2Con(info *Common.HostInfo, user string, pass string, hash []byte, haspr
// logShareInfo 记录SMB共享信息 // logShareInfo 记录SMB共享信息
func logShareInfo(info *Common.HostInfo, user string, pass string, hash []byte, shares []string) { func logShareInfo(info *Common.HostInfo, user string, pass string, hash []byte, shares []string) {
var result string credential := pass
if len(hash) > 0 {
credential = Common.HashValue
}
// 保存共享信息结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "shares-found",
Details: map[string]interface{}{
"port": info.Ports,
"service": "smb2",
"username": user,
"domain": Common.Domain,
"shares": shares,
"credential": credential,
"auth_type": map[bool]string{true: "hash", false: "password"}[len(hash) > 0],
},
}
Common.SaveResult(result)
// 控制台输出
var msg string
if Common.Domain != "" { if Common.Domain != "" {
result = fmt.Sprintf("SMB2共享信息 %s:%s %s\\%s", msg = fmt.Sprintf("SMB2共享信息 %s:%s %s\\%s", info.Host, info.Ports, Common.Domain, user)
info.Host, info.Ports, Common.Domain, user)
} else { } else {
result = fmt.Sprintf("SMB2共享信息 %s:%s %s", msg = fmt.Sprintf("SMB2共享信息 %s:%s %s", info.Host, info.Ports, user)
info.Host, info.Ports, user)
} }
if len(hash) > 0 { if len(hash) > 0 {
result += fmt.Sprintf(" Hash:%s", Common.HashValue) msg += fmt.Sprintf(" Hash:%s", Common.HashValue)
} else { } else {
result += fmt.Sprintf(" Pass:%s", pass) msg += fmt.Sprintf(" Pass:%s", pass)
} }
msg += fmt.Sprintf(" 共享:%v", shares)
result += fmt.Sprintf(" 共享:%v", shares) Common.LogInfo(msg)
Common.LogInfo(result)
} }

View File

@ -16,19 +16,36 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug("尝试匿名访问...") Common.LogDebug("尝试匿名访问...")
// 先测试匿名访问 // 先测试匿名访问
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
flag, err := SmtpConn(info, "", "") flag, err := SmtpConn(info, "", "")
if flag && err == nil { if flag && err == nil {
Common.LogSuccess("匿名访问成功!") msg := fmt.Sprintf("SMTP服务 %s 允许匿名访问", target)
Common.LogSuccess(msg)
// 保存匿名访问结果
result := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "smtp",
"type": "anonymous-access",
"anonymous": true,
},
}
Common.SaveResult(result)
return err return err
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("smtp %v:%v anonymous %v", info.Host, info.Ports, err) errlog := fmt.Sprintf("smtp %s anonymous %v", target, err)
Common.LogError(errlog) Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
@ -61,7 +78,6 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行SMTP连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -78,34 +94,48 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
msg := fmt.Sprintf("SMTP服务 %s 爆破成功 用户名: %v 密码: %v", target, user, pass)
Common.LogSuccess(msg)
// 保存成功爆破结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "smtp",
"type": "weak-password",
"username": user,
"password": pass,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("SMTP服务 %s 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err) target, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break
break // 如果不需要重试,跳出重试循环
} }
} }
} }
@ -118,25 +148,20 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
func SmtpConn(info *Common.HostInfo, user string, pass string) (bool, error) { func SmtpConn(info *Common.HostInfo, user string, pass string) (bool, error) {
host, port := info.Host, info.Ports host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
// 构造地址
addr := fmt.Sprintf("%s:%s", host, port) addr := fmt.Sprintf("%s:%s", host, port)
// 创建带超时的连接
conn, err := net.DialTimeout("tcp", addr, timeout) conn, err := net.DialTimeout("tcp", addr, timeout)
if err != nil { if err != nil {
return false, err return false, err
} }
defer conn.Close() defer conn.Close()
// 创建SMTP客户端
client, err := smtp.NewClient(conn, host) client, err := smtp.NewClient(conn, host)
if err != nil { if err != nil {
return false, err return false, err
} }
defer client.Close() defer client.Close()
// 如果提供了认证信息
if user != "" { if user != "" {
auth := smtp.PlainAuth("", user, pass, host) auth := smtp.PlainAuth("", user, pass, host)
err = client.Auth(auth) err = client.Auth(auth)
@ -145,20 +170,10 @@ func SmtpConn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
} }
// 验证是否可以发送邮件
err = client.Mail("test@test.com") err = client.Mail("test@test.com")
if err != nil { if err != nil {
return false, err return false, err
} }
// 如果成功
result := fmt.Sprintf("SMTP服务 %v:%v ", host, port)
if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else {
result += "允许匿名访问"
}
Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -19,73 +19,86 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
portNum, _ := strconv.Atoi(info.Ports) portNum, _ := strconv.Atoi(info.Ports)
defaultCommunities := []string{"public", "private", "cisco", "community"} defaultCommunities := []string{"public", "private", "cisco", "community"}
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
Common.LogDebug(fmt.Sprintf("尝试默认 community 列表 (总数: %d)", len(defaultCommunities))) Common.LogDebug(fmt.Sprintf("尝试默认 community 列表 (总数: %d)", len(defaultCommunities)))
tried := 0 tried := 0
total := len(defaultCommunities) total := len(defaultCommunities)
// 遍历所有 community
for _, community := range defaultCommunities { for _, community := range defaultCommunities {
tried++ tried++
Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试 community: %s", tried, total, community)) Common.LogDebug(fmt.Sprintf("[%d/%d] 尝试 community: %s", tried, total, community))
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
if retryCount > 0 { if retryCount > 0 {
Common.LogDebug(fmt.Sprintf("第%d次重试: community: %s", retryCount+1, community)) Common.LogDebug(fmt.Sprintf("第%d次重试: community: %s", retryCount+1, community))
} }
// 执行SNMP连接
done := make(chan struct { done := make(chan struct {
success bool success bool
sysDesc string
err error err error
}, 1) }, 1)
go func(community string) { go func(community string) {
success, err := SNMPConnect(info, community, portNum) success, sysDesc, err := SNMPConnect(info, community, portNum)
select { select {
case done <- struct { case done <- struct {
success bool success bool
sysDesc string
err error err error
}{success, err}: }{success, sysDesc, err}:
default: default:
} }
}(community) }(community)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
// 连接成功 successMsg := fmt.Sprintf("SNMP服务 %s community: %v 连接成功", target, community)
successLog := fmt.Sprintf("SNMP服务 %v:%v community: %v 连接成功", if result.sysDesc != "" {
info.Host, info.Ports, community) successMsg += fmt.Sprintf(" System: %v", result.sysDesc)
Common.LogSuccess(successLog) }
Common.LogSuccess(successMsg)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "snmp",
"community": community,
"type": "weak-community",
"system": result.sysDesc,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(timeout): case <-time.After(timeout):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("SNMP服务 %v:%v 尝试失败 community: %v 错误: %v", errlog := fmt.Sprintf("SNMP服务 %s 尝试失败 community: %v 错误: %v",
info.Host, info.Ports, community, err) target, community, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break
break // 如果不需要重试,跳出重试循环
} }
} }
@ -94,7 +107,7 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
} }
// SNMPConnect 尝试SNMP连接 // SNMPConnect 尝试SNMP连接
func SNMPConnect(info *Common.HostInfo, community string, portNum int) (bool, error) { func SNMPConnect(info *Common.HostInfo, community string, portNum int) (bool, string, error) {
host := info.Host host := info.Host
timeout := time.Duration(Common.Timeout) * time.Second timeout := time.Duration(Common.Timeout) * time.Second
@ -109,28 +122,23 @@ func SNMPConnect(info *Common.HostInfo, community string, portNum int) (bool, er
err := snmp.Connect() err := snmp.Connect()
if err != nil { if err != nil {
return false, err return false, "", err
} }
defer snmp.Conn.Close() defer snmp.Conn.Close()
oids := []string{"1.3.6.1.2.1.1.1.0"} oids := []string{"1.3.6.1.2.1.1.1.0"}
result, err := snmp.Get(oids) result, err := snmp.Get(oids)
if err != nil { if err != nil {
return false, err return false, "", err
} }
if len(result.Variables) > 0 { if len(result.Variables) > 0 {
success := fmt.Sprintf("SNMP服务 %v:%v community: %v", var sysDesc string
host, portNum, community) // 使用portNum替换port
if result.Variables[0].Type != gosnmp.NoSuchObject { if result.Variables[0].Type != gosnmp.NoSuchObject {
sysDesc := strings.TrimSpace(string(result.Variables[0].Value.([]byte))) sysDesc = strings.TrimSpace(string(result.Variables[0].Value.([]byte)))
success += fmt.Sprintf(" System: %v", sysDesc) }
return true, sysDesc, nil
} }
Common.LogSuccess(success) return false, "", fmt.Errorf("认证失败")
return true, nil
}
return false, fmt.Errorf("认证失败")
} }

View File

@ -17,8 +17,9 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["ssh"]) totalUsers := len(Common.Userdict["ssh"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -61,9 +62,39 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success { if result.success {
successLog := fmt.Sprintf("SSH认证成功 %v:%v User:%v Pass:%v", successMsg := fmt.Sprintf("SSH认证成功 %s User:%v Pass:%v", target, user, pass)
info.Host, info.Ports, user, pass) Common.LogSuccess(successMsg)
Common.LogSuccess(successLog)
// 保存结果
details := map[string]interface{}{
"port": info.Ports,
"service": "ssh",
"username": user,
"password": pass,
"type": "weak-password",
}
// 如果使用了密钥认证,添加密钥信息
if Common.SshKeyPath != "" {
details["auth_type"] = "key"
details["key_path"] = Common.SshKeyPath
details["password"] = nil
}
// 如果执行了命令,添加命令信息
if Common.Command != "" {
details["command"] = Common.Command
}
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: details,
}
Common.SaveResult(vulnResult)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
cancel() cancel()
return nil return nil
@ -75,9 +106,9 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
cancel() cancel()
if err != nil { if err != nil {
errlog := fmt.Sprintf("SSH认证失败 %v:%v User:%v Pass:%v Err:%v", errMsg := fmt.Sprintf("SSH认证失败 %s User:%v Pass:%v Err:%v",
info.Host, info.Ports, user, pass, err) target, user, pass, err)
Common.LogError(errlog) Common.LogError(errMsg)
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {

View File

@ -18,8 +18,9 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
} }
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalUsers := len(Common.Userdict["telnet"]) totalUsers := len(Common.Userdict["telnet"])
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试用户名密码组合 (总用户数: %d, 总密码数: %d)", totalUsers, totalPass))
@ -40,7 +41,6 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试: %s:%s", retryCount+1, user, pass))
} }
// 执行Telnet连接
done := make(chan struct { done := make(chan struct {
success bool success bool
noAuth bool noAuth bool
@ -59,43 +59,69 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
} }
}(user, pass) }(user, pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.noAuth { if result.noAuth {
// 无需认证 // 无需认证
result := fmt.Sprintf("Telnet服务 %v:%v 无需认证", msg := fmt.Sprintf("Telnet服务 %s 无需认证", target)
info.Host, info.Ports) Common.LogSuccess(msg)
Common.LogSuccess(result)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "telnet",
"type": "unauthorized-access",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} else if result.success { } else if result.success {
// 成功爆破 // 成功爆破
result := fmt.Sprintf("Telnet服务 %v:%v 用户名:%v 密码:%v", msg := fmt.Sprintf("Telnet服务 %s 用户名:%v 密码:%v", target, user, pass)
info.Host, info.Ports, user, pass) Common.LogSuccess(msg)
Common.LogSuccess(result)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "telnet",
"type": "weak-password",
"username": user,
"password": pass,
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v", errlog := fmt.Sprintf("Telnet连接失败 %s 用户名:%v 密码:%v 错误:%v",
info.Host, info.Ports, user, pass, err) target, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }
} }
@ -106,28 +132,21 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
// telnetConn 尝试建立Telnet连接并进行身份验证 // telnetConn 尝试建立Telnet连接并进行身份验证
func telnetConn(info *Common.HostInfo, user, pass string) (flag bool, err error) { func telnetConn(info *Common.HostInfo, user, pass string) (flag bool, err error) {
// 创建telnet客户端
client := NewTelnet(info.Host, info.Ports) client := NewTelnet(info.Host, info.Ports)
// 建立连接
if err = client.Connect(); err != nil { if err = client.Connect(); err != nil {
return false, err return false, err
} }
defer client.Close() defer client.Close()
// 设置认证信息
client.UserName = user client.UserName = user
client.Password = pass client.Password = pass
// 检测服务器类型
client.ServerType = client.MakeServerType() client.ServerType = client.MakeServerType()
// 如果是无需认证的服务器,直接返回成功
if client.ServerType == UnauthorizedAccess { if client.ServerType == UnauthorizedAccess {
return true, nil return true, nil
} }
// 尝试登录认证
err = client.Login() err = client.Login()
return false, err return false, err
} }

View File

@ -15,8 +15,9 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
modename := "vnc" modename := "vnc"
target := fmt.Sprintf("%v:%v", info.Host, info.Ports)
Common.LogDebug(fmt.Sprintf("开始扫描 %v:%v", info.Host, info.Ports)) Common.LogDebug(fmt.Sprintf("开始扫描 %s", target))
totalPass := len(Common.Passwords) totalPass := len(Common.Passwords)
Common.LogDebug(fmt.Sprintf("开始尝试密码组合 (总密码数: %d)", totalPass)) Common.LogDebug(fmt.Sprintf("开始尝试密码组合 (总密码数: %d)", totalPass))
@ -33,7 +34,6 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
Common.LogDebug(fmt.Sprintf("第%d次重试密码: %s", retryCount+1, pass)) Common.LogDebug(fmt.Sprintf("第%d次重试密码: %s", retryCount+1, pass))
} }
// 执行VNC连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
@ -50,37 +50,48 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
} }
}(pass) }(pass)
// 等待结果或超时
var err error var err error
select { select {
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
// 连接成功 // 连接成功
successLog := fmt.Sprintf("%s://%v:%v 密码: %v", successLog := fmt.Sprintf("%s://%s 密码: %v", modename, target, pass)
modename, info.Host, info.Ports, pass)
Common.LogSuccess(successLog) Common.LogSuccess(successLog)
// 保存结果
vulnResult := &Common.ScanResult{
Time: time.Now(),
Type: Common.VULN,
Target: info.Host,
Status: "vulnerable",
Details: map[string]interface{}{
"port": info.Ports,
"service": "vnc",
"password": pass,
"type": "weak-password",
},
}
Common.SaveResult(vulnResult)
return nil return nil
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("%s://%v:%v 尝试密码: %v 错误: %v", errlog := fmt.Sprintf("%s://%s 尝试密码: %v 错误: %v",
modename, info.Host, info.Ports, pass, err) modename, target, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 检查是否是需要重试的错误
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 { if retryCount == maxRetries-1 {
continue continue
} }
continue // 继续重试 continue
} }
} }
break // 如果不需要重试,跳出重试循环 break
} }
} }

View File

@ -198,7 +198,6 @@ func geturl(info *Common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
if flag != 2 { if flag != 2 {
// 处理编码 // 处理编码
if !utf8.Valid(body) { if !utf8.Valid(body) {
Common.LogDebug("检测到非UTF8编码尝试GBK解码")
body, _ = simplifiedchinese.GBK.NewDecoder().Bytes(body) body, _ = simplifiedchinese.GBK.NewDecoder().Bytes(body)
} }
@ -208,22 +207,53 @@ func geturl(info *Common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
if length == "" { if length == "" {
length = fmt.Sprintf("%v", len(body)) length = fmt.Sprintf("%v", len(body))
} }
Common.LogDebug(fmt.Sprintf("提取的标题: %s, 内容长度: %s", title, length))
// 处理重定向 // 收集服务器信息
serverInfo := make(map[string]interface{})
serverInfo["title"] = title
serverInfo["length"] = length
serverInfo["status_code"] = resp.StatusCode
// 收集响应头信息
for k, v := range resp.Header {
if len(v) > 0 {
serverInfo[strings.ToLower(k)] = v[0]
}
}
// 检查重定向
redirURL, err1 := resp.Location() redirURL, err1 := resp.Location()
if err1 == nil { if err1 == nil {
reurl = redirURL.String() reurl = redirURL.String()
Common.LogDebug(fmt.Sprintf("检测到重定向URL: %s", reurl)) serverInfo["redirect_url"] = reurl
} }
// 输出结果 // 保存扫描结果
result := fmt.Sprintf("网站标题 %-25v 状态码:%-3v 长度:%-6v 标题:%v", result := &Common.ScanResult{
Time: time.Now(),
Type: Common.SERVICE,
Target: info.Host,
Status: "identified",
Details: map[string]interface{}{
"port": info.Ports,
"service": "http",
"title": title,
"url": resp.Request.URL.String(),
"status_code": resp.StatusCode,
"length": length,
"server_info": serverInfo,
"fingerprints": info.Infostr, // 指纹信息
},
}
Common.SaveResult(result)
// 输出控制台日志
logMsg := fmt.Sprintf("网站标题 %-25v 状态码:%-3v 长度:%-6v 标题:%v",
resp.Request.URL, resp.StatusCode, length, title) resp.Request.URL, resp.StatusCode, length, title)
if reurl != "" { if reurl != "" {
result += fmt.Sprintf(" 重定向地址: %s", reurl) logMsg += fmt.Sprintf(" 重定向地址: %s", reurl)
} }
Common.LogSuccess(result) Common.LogSuccess(logMsg)
} }
// 返回结果 // 返回结果

10
main.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"github.com/shadow1ng/fscan/Common" "github.com/shadow1ng/fscan/Common"
"github.com/shadow1ng/fscan/Core" "github.com/shadow1ng/fscan/Core"
"os" "os"
@ -8,12 +9,17 @@ import (
func main() { func main() {
Common.InitLogger() Common.InitLogger()
defer Common.CloseLogger() // 确保程序退出时关闭日志文件
var Info Common.HostInfo var Info Common.HostInfo
Common.Flag(&Info) Common.Flag(&Info)
if err := Common.Parse(&Info); err != nil { if err := Common.Parse(&Info); err != nil {
os.Exit(1) // 直接退出即可,日志已经同步写入 os.Exit(1)
} }
// 初始化输出系统,如果失败则直接退出
if err := Common.InitOutput(); err != nil {
Common.LogError(fmt.Sprintf("初始化输出系统失败: %v", err))
os.Exit(1) // 关键修改:初始化失败时直接退出
}
defer Common.CloseOutput()
Core.Scan(Info) Core.Scan(Info)
} }