mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-05-05 10:17:49 +00:00
refactor: 全部优化为多线程
This commit is contained in:
parent
ed69e41001
commit
c004762a8c
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ result.txt
|
||||
main
|
||||
.idea
|
||||
fscan.exe
|
||||
fscan
|
||||
|
@ -26,7 +26,7 @@ var Userdict = map[string][]string{
|
||||
"neo4j": {"neo4j", "admin", "root", "test"},
|
||||
}
|
||||
|
||||
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "P@ssword123", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789", "elastic123"}
|
||||
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "Password", "P@ssword123", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789", "elastic123"}
|
||||
|
||||
var Outputfile = "result.txt"
|
||||
var IsSave = true
|
||||
@ -92,6 +92,7 @@ var (
|
||||
// 爆破配置
|
||||
DisableBrute bool // 原IsBrute
|
||||
BruteThreads int // 原BruteThread
|
||||
MaxRetries int // 最大重试次数
|
||||
|
||||
// 其他配置
|
||||
RemotePath string // 原Path
|
||||
|
@ -114,6 +114,7 @@ func Flag(Info *HostInfo) {
|
||||
// 暴力破解配置
|
||||
flag.BoolVar(&DisableBrute, "nobr", false, "禁用密码暴力破解")
|
||||
flag.IntVar(&BruteThreads, "br", 1, "设置密码破解线程数")
|
||||
flag.IntVar(&MaxRetries, "retry", 3, "设置最大重试次数")
|
||||
|
||||
// 其他配置
|
||||
flag.StringVar(&RemotePath, "path", "", "指定FCG/SMB远程文件路径")
|
||||
|
@ -137,13 +137,13 @@ func LogError(errinfo interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// CheckErrs 检查是否为已知错误
|
||||
func CheckErrs(err error) bool {
|
||||
// CheckErrs 检查是否为需要重试的错误
|
||||
func CheckErrs(err error) error {
|
||||
if err == nil {
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
// 已知错误列表
|
||||
// 已知需要重试的错误列表
|
||||
errs := []string{
|
||||
"closed by the remote host", "too many connections",
|
||||
"EOF", "A connection attempt failed",
|
||||
@ -159,9 +159,10 @@ func CheckErrs(err error) bool {
|
||||
errLower := strings.ToLower(err.Error())
|
||||
for _, key := range errs {
|
||||
if strings.Contains(errLower, strings.ToLower(key)) {
|
||||
return true
|
||||
time.Sleep(3 * time.Second)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -14,39 +15,127 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试默认账户
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := ActiveMQConn(info, "admin", "admin")
|
||||
if flag {
|
||||
return nil
|
||||
}
|
||||
tmperr = err
|
||||
if err != nil {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["activemq"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["activemq"] {
|
||||
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++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行连接测试
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
flag, err := ActiveMQConn(info, user, pass)
|
||||
if flag {
|
||||
return nil
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{flag, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["activemq"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -14,37 +15,126 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
// 首先测试无认证访问
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := CassandraConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
if err != nil && Common.CheckErrs(err) != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["cassandra"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["cassandra"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := CassandraConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := CassandraConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["cassandra"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -16,40 +17,127 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试无认证访问
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := ElasticConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
if err != nil && Common.CheckErrs(err) != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["elastic"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["elastic"] {
|
||||
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++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行连接尝试
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
flag, err := ElasticConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{flag, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 记录错误信息
|
||||
errlog := fmt.Sprintf("[-] Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["elastic"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
123
Plugins/FTP.go
123
Plugins/FTP.go
@ -5,57 +5,140 @@ import (
|
||||
"github.com/jlaffaye/ftp"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FtpScan 执行FTP服务扫描
|
||||
func FtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
// 如果已开启暴力破解则直接返回
|
||||
if Common.DisableBrute {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试匿名登录
|
||||
// 先尝试匿名登录
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := FtpConn(info, "anonymous", "")
|
||||
if flag && err == nil {
|
||||
// 匿名登录成功,不需要继续尝试其他密码
|
||||
return nil
|
||||
}
|
||||
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
|
||||
Common.LogError(errlog)
|
||||
tmperr = err
|
||||
if Common.CheckErrs(err) {
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["ftp"])*len(Common.Passwords))
|
||||
|
||||
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)
|
||||
|
||||
flag, err := FtpConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 记录错误信息
|
||||
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行FTP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := FtpConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["ftp"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
101
Plugins/IMAP.go
101
Plugins/IMAP.go
@ -8,6 +8,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -16,31 +17,107 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试用户名密码组合
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["imap"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["imap"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := IMAPConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行IMAP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := IMAPConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["imap"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
115
Plugins/Kafka.go
115
Plugins/Kafka.go
@ -5,6 +5,7 @@ import (
|
||||
"github.com/IBM/sarama"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -14,37 +15,127 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试无认证访问
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := KafkaConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
return nil
|
||||
}
|
||||
if err != nil && Common.CheckErrs(err) != nil {
|
||||
if retryCount < maxRetries-1 {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["kafka"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["kafka"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := KafkaConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行Kafka连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := KafkaConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["kafka"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
107
Plugins/LDAP.go
107
Plugins/LDAP.go
@ -5,6 +5,7 @@ import (
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -14,38 +15,118 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试匿名访问
|
||||
// 首先尝试匿名访问
|
||||
flag, err := LDAPConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["ldap"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["ldap"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := LDAPConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行LDAP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := LDAPConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["ldap"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
105
Plugins/MSSQL.go
105
Plugins/MSSQL.go
@ -6,6 +6,7 @@ import (
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,34 +16,108 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试用户名密码组合
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["mssql"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["mssql"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
// 替换密码中的用户名占位符
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := MssqlConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 记录错误信息
|
||||
errlog := fmt.Sprintf("[-] MSSQL %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行MSSQL连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := MssqlConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] MSSQL %v:%v %v %v %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["mssql"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
139
Plugins/MySQL.go
139
Plugins/MySQL.go
@ -6,6 +6,7 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,34 +16,138 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 添加成功标志通道
|
||||
successChan := make(chan struct{}, 1)
|
||||
defer close(successChan)
|
||||
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["mysql"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["mysql"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
// 替换密码中的用户名占位符
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := MysqlConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 检查是否已经成功
|
||||
select {
|
||||
case <-successChan:
|
||||
resultChan <- nil
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
// 记录错误信息
|
||||
errlog := fmt.Sprintf("[-] MySQL %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行MySQL连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := MysqlConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 连接成功
|
||||
select {
|
||||
case successChan <- struct{}{}: // 标记成功
|
||||
successLog := fmt.Sprintf("[+] MySQL %v:%v %v %v",
|
||||
info.Host, info.Ports, task.user, task.pass)
|
||||
Common.LogSuccess(successLog)
|
||||
default:
|
||||
}
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] MySQL %v:%v %v %v %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 特殊处理认证失败的情况
|
||||
if strings.Contains(err.Error(), "Access denied") {
|
||||
break // 跳出重试循环,继续下一个密码
|
||||
}
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["mysql"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if !strings.Contains(err.Error(), "Access denied") {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
@ -74,8 +179,6 @@ func MysqlConn(info *Common.HostInfo, user string, pass string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// 连接成功
|
||||
result := fmt.Sprintf("[+] MySQL %v:%v:%v %v", host, port, username, password)
|
||||
Common.LogSuccess(result)
|
||||
// 连接成功,只返回结果,不打印日志
|
||||
return true, nil
|
||||
}
|
||||
|
122
Plugins/Neo4j.go
122
Plugins/Neo4j.go
@ -5,6 +5,7 @@ import (
|
||||
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -14,43 +15,128 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试无认证访问
|
||||
flag, err := Neo4jConn(info, "", "")
|
||||
// 首先测试无认证访问和默认凭证
|
||||
initialChecks := []struct {
|
||||
user string
|
||||
pass string
|
||||
}{
|
||||
{"", ""}, // 无认证
|
||||
{"neo4j", "neo4j"}, // 默认凭证
|
||||
}
|
||||
|
||||
for _, check := range initialChecks {
|
||||
flag, err := Neo4jConn(info, check.user, check.pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 测试默认凭证
|
||||
flag, err = Neo4jConn(info, "neo4j", "neo4j")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 尝试其他用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["neo4j"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["neo4j"] {
|
||||
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++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行Neo4j连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
flag, err := Neo4jConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{flag, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["neo4j"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
_ "github.com/sijms/go-ora/v2"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,34 +16,112 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["oracle"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["oracle"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
// 替换密码中的用户名占位符
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := OracleConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 记录错误信息
|
||||
errlog := fmt.Sprintf("[-] Oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行Oracle连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := OracleConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Oracle %v:%v %v %v %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["oracle"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
109
Plugins/POP3.go
109
Plugins/POP3.go
@ -7,6 +7,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,30 +16,116 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["pop3"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["pop3"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := POP3Conn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行POP3连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := POP3Conn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 连接成功
|
||||
successLog := fmt.Sprintf("[+] POP3服务 %v:%v 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, task.user, task.pass)
|
||||
Common.LogSuccess(successLog)
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["pop3"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,34 +16,112 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["postgresql"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["postgresql"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
// 替换密码中的用户名占位符
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := PostgresConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 记录错误信息
|
||||
errlog := fmt.Sprintf("[-] PostgreSQL %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行PostgreSQL连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := PostgresConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] PostgreSQL %v:%v %v %v %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["postgresql"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,37 +16,121 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试默认账户 guest/guest
|
||||
flag, err := RabbitMQConn(info, "guest", "guest")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["rabbitmq"])*len(Common.Passwords)+1) // +1 是为了加入guest账号
|
||||
|
||||
// 尝试用户名密码组合
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 先加入默认账号guest/guest
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{"guest", "guest"}
|
||||
|
||||
// 生成其他用户名密码组合任务
|
||||
for _, user := range Common.Userdict["rabbitmq"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := RabbitMQConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行RabbitMQ连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := RabbitMQConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
result := fmt.Sprintf("[+] RabbitMQ服务 %v:%v 连接成功 用户名: %v 密码: %v",
|
||||
info.Host, info.Ports, task.user, task.pass)
|
||||
Common.LogSuccess(result)
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["rabbitmq"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
103
Plugins/Redis.go
103
Plugins/Redis.go
@ -8,6 +8,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -20,7 +21,7 @@ var (
|
||||
func RedisScan(info *Common.HostInfo) (tmperr error) {
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
// 尝试无密码连接
|
||||
// 先尝试无密码连接
|
||||
flag, err := RedisUnauth(info)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
@ -30,30 +31,102 @@ func RedisScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
// 尝试密码暴力破解
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 创建任务通道
|
||||
taskChan := make(chan string, len(Common.Passwords))
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有密码任务
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", "redis", -1)
|
||||
taskChan <- pass
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := RedisConn(info, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
for pass := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 记录错误信息
|
||||
errlog := fmt.Sprintf("[-] Redis %v:%v %v %v", info.Host, info.Ports, pass, err)
|
||||
// 执行Redis连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(pass string) {
|
||||
success, err := RedisConn(info, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Redis %v:%v %v %v",
|
||||
info.Host, info.Ports, pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Println("[+] Redis扫描模块结束...")
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
115
Plugins/Rsync.go
115
Plugins/Rsync.go
@ -5,6 +5,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -14,38 +15,130 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试匿名访问
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := RsyncConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
if err != nil {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["rsync"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["rsync"] {
|
||||
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++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行Rsync连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
flag, err := RsyncConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{flag && err == nil, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["rsync"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
139
Plugins/SMB.go
139
Plugins/SMB.go
@ -6,60 +6,133 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"github.com/stacktitan/smb/smb"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SmbScan 执行SMB服务的认证扫描
|
||||
func SmbScan(info *Common.HostInfo) (tmperr error) {
|
||||
// 如果未启用暴力破解则直接返回
|
||||
if Common.DisableBrute {
|
||||
return nil
|
||||
}
|
||||
|
||||
startTime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 遍历用户名和密码字典进行认证尝试
|
||||
// 创建任务通道
|
||||
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.Replace(pass, "{user}", user, -1)
|
||||
|
||||
// 执行带超时的认证
|
||||
success, err := doWithTimeOut(info, user, pass)
|
||||
|
||||
if success && err == nil {
|
||||
// 认证成功,记录结果
|
||||
var result string
|
||||
if Common.Domain != "" {
|
||||
result = fmt.Sprintf("[✓] SMB认证成功 %v:%v Domain:%v\\%v Pass:%v",
|
||||
info.Host, info.Ports, Common.Domain, user, pass)
|
||||
} else {
|
||||
result = fmt.Sprintf("[✓] SMB认证成功 %v:%v User:%v Pass:%v",
|
||||
info.Host, info.Ports, user, pass)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
return err
|
||||
} else {
|
||||
// 认证失败,记录错误
|
||||
errorMsg := fmt.Sprintf("[x] SMB认证失败 %v:%v User:%v Pass:%v Err:%v",
|
||||
info.Host, info.Ports, user, pass,
|
||||
strings.ReplaceAll(err.Error(), "\n", ""))
|
||||
Common.LogError(errorMsg)
|
||||
tmperr = err
|
||||
|
||||
// 检查是否需要中断扫描
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
startTime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
timeoutLimit := int64(len(Common.Userdict["smb"])*len(Common.Passwords)) * Common.Timeout
|
||||
if time.Now().Unix()-startTime > timeoutLimit {
|
||||
if time.Now().Unix()-startTime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行SMB认证
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := doWithTimeOut(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 认证成功
|
||||
var successLog string
|
||||
if Common.Domain != "" {
|
||||
successLog = fmt.Sprintf("[✓] SMB认证成功 %v:%v Domain:%v\\%v Pass:%v",
|
||||
info.Host, info.Ports, Common.Domain, task.user, task.pass)
|
||||
} else {
|
||||
successLog = fmt.Sprintf("[✓] SMB认证成功 %v:%v User:%v Pass:%v",
|
||||
info.Host, info.Ports, task.user, task.pass)
|
||||
}
|
||||
Common.LogSuccess(successLog)
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[x] SMB认证失败 %v:%v User:%v Pass:%v Err:%v",
|
||||
info.Host, info.Ports, task.user, task.pass,
|
||||
strings.ReplaceAll(err.Error(), "\n", ""))
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
260
Plugins/SMB2.go
260
Plugins/SMB2.go
@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hirochachacha/go-smb2"
|
||||
@ -13,79 +14,269 @@ import (
|
||||
|
||||
// SmbScan2 执行SMB2服务的认证扫描,支持密码和哈希两种认证方式
|
||||
func SmbScan2(info *Common.HostInfo) (tmperr error) {
|
||||
|
||||
// 如果未启用暴力破解则直接返回
|
||||
if Common.DisableBrute {
|
||||
return nil
|
||||
}
|
||||
|
||||
hasprint := false
|
||||
startTime := time.Now().Unix()
|
||||
|
||||
// 使用哈希认证模式
|
||||
if len(Common.HashBytes) > 0 {
|
||||
return smbHashScan(info, hasprint, startTime)
|
||||
return smbHashScan(info)
|
||||
}
|
||||
|
||||
// 使用密码认证模式
|
||||
return smbPasswordScan(info, hasprint, startTime)
|
||||
return smbPasswordScan(info)
|
||||
}
|
||||
|
||||
// smbHashScan 使用哈希进行认证扫描
|
||||
func smbHashScan(info *Common.HostInfo, hasprint bool, startTime int64) error {
|
||||
func smbHashScan(info *Common.HostInfo) error {
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
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 {
|
||||
success, err, printed := Smb2Con(info, user, "", hash, hasprint)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
hash []byte
|
||||
}{user, hash}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
var hasPrintMutex sync.Mutex
|
||||
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
startTime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-startTime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行SMB2认证
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
printed bool
|
||||
})
|
||||
|
||||
go func(user string, hash []byte) {
|
||||
hasPrintMutex.Lock()
|
||||
currentHasPrint := hasprint
|
||||
hasPrintMutex.Unlock()
|
||||
|
||||
success, err, printed := Smb2Con(info, user, "", hash, currentHasPrint)
|
||||
|
||||
if printed {
|
||||
hasPrintMutex.Lock()
|
||||
hasprint = true
|
||||
hasPrintMutex.Unlock()
|
||||
}
|
||||
|
||||
if success {
|
||||
logSuccessfulAuth(info, user, "", hash)
|
||||
return err
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
printed bool
|
||||
}{success, err, printed}
|
||||
}(task.user, task.hash)
|
||||
|
||||
// 等待结果或超时
|
||||
select {
|
||||
case result := <-done:
|
||||
if result.success {
|
||||
logSuccessfulAuth(info, task.user, "", task.hash)
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
|
||||
logFailedAuth(info, user, "", hash, err)
|
||||
if result.err != nil {
|
||||
logFailedAuth(info, task.user, "", task.hash, result.err)
|
||||
|
||||
if shouldStopScan(err, startTime, len(Common.Userdict["smb"])*len(Common.HashBytes)) {
|
||||
return err
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(result.err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- result.err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
logFailedAuth(info, task.user, "", task.hash, fmt.Errorf("连接超时"))
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
|
||||
if len(Common.HashValue) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// smbPasswordScan 使用密码进行认证扫描
|
||||
func smbPasswordScan(info *Common.HostInfo, hasprint bool, startTime int64) error {
|
||||
func smbPasswordScan(info *Common.HostInfo) error {
|
||||
maxRetries := Common.MaxRetries
|
||||
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)
|
||||
success, err, printed := Smb2Con(info, user, pass, []byte{}, hasprint)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
var hasPrintMutex sync.Mutex
|
||||
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
startTime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-startTime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行SMB2认证
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
printed bool
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
hasPrintMutex.Lock()
|
||||
currentHasPrint := hasprint
|
||||
hasPrintMutex.Unlock()
|
||||
|
||||
success, err, printed := Smb2Con(info, user, pass, []byte{}, currentHasPrint)
|
||||
|
||||
if printed {
|
||||
hasPrintMutex.Lock()
|
||||
hasprint = true
|
||||
hasPrintMutex.Unlock()
|
||||
}
|
||||
|
||||
if success {
|
||||
logSuccessfulAuth(info, user, pass, []byte{})
|
||||
return err
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
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
|
||||
}
|
||||
|
||||
logFailedAuth(info, user, pass, []byte{}, err)
|
||||
if result.err != nil {
|
||||
logFailedAuth(info, task.user, task.pass, []byte{}, result.err)
|
||||
|
||||
if shouldStopScan(err, startTime, len(Common.Userdict["smb"])*len(Common.Passwords)) {
|
||||
return err
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(result.err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- result.err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
logFailedAuth(info, task.user, task.pass, []byte{}, fmt.Errorf("连接超时"))
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
|
||||
if len(Common.HashValue) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
fmt.Println("[+] Smb2扫描模块结束...")
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -93,10 +284,10 @@ func smbPasswordScan(info *Common.HostInfo, hasprint bool, startTime int64) erro
|
||||
func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
|
||||
var result string
|
||||
if Common.Domain != "" {
|
||||
result = fmt.Sprintf("[✓] SMB2认证成功 %v:%v Domain:%v\\%v ",
|
||||
result = fmt.Sprintf("[+] SMB2认证成功 %v:%v Domain:%v\\%v ",
|
||||
info.Host, info.Ports, Common.Domain, user)
|
||||
} else {
|
||||
result = fmt.Sprintf("[✓] SMB2认证成功 %v:%v User:%v ",
|
||||
result = fmt.Sprintf("[+] SMB2认证成功 %v:%v User:%v ",
|
||||
info.Host, info.Ports, user)
|
||||
}
|
||||
|
||||
@ -112,29 +303,16 @@ func logSuccessfulAuth(info *Common.HostInfo, user, pass string, hash []byte) {
|
||||
func logFailedAuth(info *Common.HostInfo, user, pass string, hash []byte, err error) {
|
||||
var errlog string
|
||||
if len(hash) > 0 {
|
||||
errlog = fmt.Sprintf("[x] SMB2认证失败 %v:%v User:%v HashValue:%v Err:%v",
|
||||
errlog = fmt.Sprintf("[-] SMB2认证失败 %v:%v User:%v HashValue:%v Err:%v",
|
||||
info.Host, info.Ports, user, Common.HashValue, err)
|
||||
} else {
|
||||
errlog = fmt.Sprintf("[x] SMB2认证失败 %v:%v User:%v Pass:%v Err:%v",
|
||||
errlog = fmt.Sprintf("[-] SMB2认证失败 %v:%v User:%v Pass:%v Err:%v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
}
|
||||
errlog = strings.ReplaceAll(errlog, "\n", " ")
|
||||
Common.LogError(errlog)
|
||||
}
|
||||
|
||||
// shouldStopScan 检查是否应该停止扫描
|
||||
func shouldStopScan(err error, startTime int64, totalAttempts int) bool {
|
||||
if Common.CheckErrs(err) {
|
||||
return true
|
||||
}
|
||||
|
||||
if time.Now().Unix()-startTime > (int64(totalAttempts) * Common.Timeout) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Smb2Con 尝试SMB2连接并进行认证,检查共享访问权限
|
||||
func Smb2Con(info *Common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
|
||||
// 建立TCP连接
|
||||
|
117
Plugins/SMTP.go
117
Plugins/SMTP.go
@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,39 +16,129 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试匿名访问
|
||||
// 先测试匿名访问
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
flag, err := SmtpConn(info, "", "")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["smtp"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["smtp"] {
|
||||
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++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行SMTP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
flag, err := SmtpConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{flag, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// 超时检查
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["smtp"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
101
Plugins/SNMP.go
101
Plugins/SNMP.go
@ -6,6 +6,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -15,33 +16,109 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
portNum, _ := strconv.Atoi(info.Ports) // 添加端口转换
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先尝试默认community strings
|
||||
portNum, _ := strconv.Atoi(info.Ports)
|
||||
defaultCommunities := []string{"public", "private", "cisco", "community"}
|
||||
|
||||
// 创建任务通道
|
||||
taskChan := make(chan string, len(defaultCommunities))
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有community任务
|
||||
for _, community := range defaultCommunities {
|
||||
flag, err := SNMPConnect(info, community, portNum) // 传入转换后的端口
|
||||
if flag && err == nil {
|
||||
return err
|
||||
taskChan <- community
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for community := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
if time.Now().Unix()-starttime > int64(timeout.Seconds()) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
// 执行SNMP连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(community string) {
|
||||
success, err := SNMPConnect(info, community, portNum)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(community)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 连接成功
|
||||
successLog := fmt.Sprintf("[+] SNMP服务 %v:%v community: %v 连接成功",
|
||||
info.Host, info.Ports, community)
|
||||
Common.LogSuccess(successLog)
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(timeout):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] SNMP服务 %v:%v 尝试失败 community: %v 错误: %v",
|
||||
info.Host, info.Ports, community, err)
|
||||
Common.LogError(errlog)
|
||||
tmperr = err
|
||||
|
||||
// 修正超时计算
|
||||
timeout := time.Duration(Common.Timeout) * time.Second
|
||||
if time.Now().Unix()-starttime > int64(timeout.Seconds())*int64(len(defaultCommunities)) {
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
@ -16,13 +16,13 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
threads := Common.BruteThreads // 使用 BruteThreads 来控制线程数
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["ssh"])*len(Common.Passwords))
|
||||
|
||||
// 创建结果通道
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有任务
|
||||
@ -37,20 +37,19 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for task := range taskChan {
|
||||
// 为每个任务创建结果通道
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
// 执行SSH连接
|
||||
go func(user, pass string) {
|
||||
success, err := SshConn(info, user, pass)
|
||||
done <- struct {
|
||||
@ -59,7 +58,6 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
@ -77,22 +75,28 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
// 检查是否是已知错误,如果是则等待3秒后重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
if Common.SshKeyPath != "" {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
@ -102,7 +106,7 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
if Common.CheckErrs(err) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -8,54 +8,131 @@ import (
|
||||
"net"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TelnetScan 执行Telnet服务扫描和密码爆破
|
||||
func TelnetScan(info *Common.HostInfo) (tmperr error) {
|
||||
// 检查是否禁用暴力破解
|
||||
if Common.DisableBrute {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 遍历用户名密码字典进行尝试
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["telnet"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["telnet"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
// 替换密码中的用户名占位符
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
// 尝试Telnet连接
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 执行Telnet连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
noAuth bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
flag, err := telnetConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
noAuth bool
|
||||
err error
|
||||
}{err == nil, flag, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 处理连接结果
|
||||
if flag {
|
||||
// 无需认证的情况
|
||||
result := fmt.Sprintf("[+] Telnet服务 %v:%v 无需认证", info.Host, info.Ports)
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.noAuth {
|
||||
// 无需认证
|
||||
result := fmt.Sprintf("[+] Telnet服务 %v:%v 无需认证",
|
||||
info.Host, info.Ports)
|
||||
Common.LogSuccess(result)
|
||||
return nil
|
||||
} else if err == nil {
|
||||
// 成功爆破到密码
|
||||
result := fmt.Sprintf("[+] Telnet服务 %v:%v 用户名:%v 密码:%v", info.Host, info.Ports, user, pass)
|
||||
resultChan <- nil
|
||||
return
|
||||
} else if result.success {
|
||||
// 成功爆破
|
||||
result := fmt.Sprintf("[+] Telnet服务 %v:%v 用户名:%v 密码:%v",
|
||||
info.Host, info.Ports, task.user, task.pass)
|
||||
Common.LogSuccess(result)
|
||||
return nil
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v",
|
||||
info.Host, info.Ports, user, pass, err)
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
tmperr = err
|
||||
|
||||
// 检查是否存在严重错误需要中断
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["telnet"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
return fmt.Errorf("扫描超时")
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -16,31 +17,112 @@ func TomcatScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["tomcat"])*len(Common.Passwords))
|
||||
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["tomcat"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := TomcatConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] Tomcat Manager %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行Tomcat连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := TomcatConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Tomcat Manager %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["tomcat"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
109
Plugins/VNC.go
109
Plugins/VNC.go
@ -5,46 +5,117 @@ import (
|
||||
"github.com/mitchellh/go-vnc"
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// VncScan 执行VNC服务扫描及密码尝试
|
||||
func VncScan(info *Common.HostInfo) (tmperr error) {
|
||||
// 如果已开启暴力破解则直接返回
|
||||
if Common.DisableBrute {
|
||||
return
|
||||
}
|
||||
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
modename := "vnc"
|
||||
|
||||
// 创建任务通道
|
||||
taskChan := make(chan string, len(Common.Passwords))
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有密码任务
|
||||
for _, pass := range Common.Passwords {
|
||||
taskChan <- pass
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
// 遍历密码字典尝试连接
|
||||
for _, pass := range Common.Passwords {
|
||||
flag, err := VncConn(info, pass)
|
||||
|
||||
if flag && err == nil {
|
||||
// 连接成功,记录结果
|
||||
result := fmt.Sprintf("[+] %s://%v:%v 密码: %v", modename, info.Host, info.Ports, pass)
|
||||
Common.LogSuccess(result)
|
||||
return err
|
||||
for pass := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
// 连接失败,记录错误信息
|
||||
// 执行VNC连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(pass string) {
|
||||
success, err := VncConn(info, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
// 连接成功
|
||||
successLog := fmt.Sprintf("[+] %s://%v:%v 密码: %v",
|
||||
modename, info.Host, info.Ports, pass)
|
||||
Common.LogSuccess(successLog)
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] %s://%v:%v 尝试密码: %v 错误: %v",
|
||||
modename, info.Host, info.Ports, pass, err)
|
||||
Common.LogError(errlog)
|
||||
tmperr = err
|
||||
|
||||
// 检查是否需要中断扫描
|
||||
if Common.CheckErrs(err) {
|
||||
// 检查是否是需要重试的错误
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Passwords)) * Common.Timeout) {
|
||||
return fmt.Errorf("扫描超时")
|
||||
}
|
||||
}
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -32,49 +33,132 @@ func WmiExec(info *Common.HostInfo) (tmperr error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
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"] {
|
||||
PASS:
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
// 如果是32位hash值,只尝试一次密码
|
||||
if len(Common.HashValue) == 32 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := Wmiexec(info, user, pass, Common.HashValue)
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v", info.Host, 445, user, pass, err)
|
||||
errlog = strings.Replace(errlog, "\n", "", -1)
|
||||
Common.LogError(errlog)
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
if flag {
|
||||
var result string
|
||||
// 执行WMI连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := Wmiexec(info, user, pass, Common.HashValue)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success {
|
||||
// 成功连接
|
||||
var successLog string
|
||||
if Common.Domain != "" {
|
||||
result = fmt.Sprintf("[+] WmiExec %v:%v:%v\\%v ", info.Host, info.Ports, Common.Domain, user)
|
||||
successLog = fmt.Sprintf("[+] WmiExec %v:%v:%v\\%v ",
|
||||
info.Host, info.Ports, Common.Domain, task.user)
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] WmiExec %v:%v:%v ", info.Host, info.Ports, user)
|
||||
successLog = fmt.Sprintf("[+] WmiExec %v:%v:%v ",
|
||||
info.Host, info.Ports, task.user)
|
||||
}
|
||||
|
||||
if Common.HashValue != "" {
|
||||
result += "hash: " + Common.HashValue
|
||||
successLog += "hash: " + Common.HashValue
|
||||
} else {
|
||||
result += pass
|
||||
successLog += task.pass
|
||||
}
|
||||
Common.LogSuccess(result)
|
||||
return err
|
||||
} else {
|
||||
tmperr = err
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
Common.LogSuccess(successLog)
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["smb"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
return err
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v",
|
||||
info.Host, 445, task.user, task.pass, err)
|
||||
errlog = strings.Replace(errlog, "\n", "", -1)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
if len(Common.HashValue) == 32 {
|
||||
break PASS
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/shadow1ng/fscan/Common"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -16,37 +17,134 @@ func ZabbixScan(info *Common.HostInfo) (tmperr error) {
|
||||
return
|
||||
}
|
||||
|
||||
starttime := time.Now().Unix()
|
||||
maxRetries := Common.MaxRetries
|
||||
threads := Common.BruteThreads
|
||||
|
||||
// 首先测试默认账户
|
||||
flag, err := ZabbixConn(info, "Admin", "zabbix")
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 先测试默认账号
|
||||
defaultDone := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func() {
|
||||
success, err := ZabbixConn(info, "Admin", "zabbix")
|
||||
defaultDone <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case result := <-defaultDone:
|
||||
if result.success && result.err == nil {
|
||||
return result.err
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
Common.LogError(fmt.Sprintf("[-] Zabbix默认账号连接超时 %v:%v", info.Host, info.Ports))
|
||||
}
|
||||
|
||||
// 尝试用户名密码组合
|
||||
// 创建任务通道
|
||||
taskChan := make(chan struct {
|
||||
user string
|
||||
pass string
|
||||
}, len(Common.Userdict["zabbix"])*len(Common.Passwords))
|
||||
resultChan := make(chan error, threads)
|
||||
|
||||
// 生成所有用户名密码组合任务
|
||||
for _, user := range Common.Userdict["zabbix"] {
|
||||
for _, pass := range Common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
taskChan <- struct {
|
||||
user string
|
||||
pass string
|
||||
}{user, pass}
|
||||
}
|
||||
}
|
||||
close(taskChan)
|
||||
|
||||
flag, err := ZabbixConn(info, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
// 启动工作线程
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < threads; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
starttime := time.Now().Unix()
|
||||
|
||||
for task := range taskChan {
|
||||
// 重试循环
|
||||
for retryCount := 0; retryCount < maxRetries; retryCount++ {
|
||||
// 检查是否超时
|
||||
if time.Now().Unix()-starttime > int64(Common.Timeout) {
|
||||
resultChan <- fmt.Errorf("扫描超时")
|
||||
return
|
||||
}
|
||||
|
||||
errlog := fmt.Sprintf("[-] Zabbix服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v", info.Host, info.Ports, user, pass, err)
|
||||
// 执行Zabbix连接
|
||||
done := make(chan struct {
|
||||
success bool
|
||||
err error
|
||||
})
|
||||
|
||||
go func(user, pass string) {
|
||||
success, err := ZabbixConn(info, user, pass)
|
||||
done <- struct {
|
||||
success bool
|
||||
err error
|
||||
}{success, err}
|
||||
}(task.user, task.pass)
|
||||
|
||||
// 等待结果或超时
|
||||
var err error
|
||||
select {
|
||||
case result := <-done:
|
||||
err = result.err
|
||||
if result.success && err == nil {
|
||||
resultChan <- nil
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Duration(Common.Timeout) * time.Second):
|
||||
err = fmt.Errorf("连接超时")
|
||||
}
|
||||
|
||||
// 处理错误情况
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Zabbix服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
|
||||
info.Host, info.Ports, task.user, task.pass, err)
|
||||
Common.LogError(errlog)
|
||||
|
||||
// 检查是否需要重试
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
if retryCount == maxRetries-1 {
|
||||
resultChan <- err
|
||||
return
|
||||
}
|
||||
continue // 继续重试
|
||||
}
|
||||
}
|
||||
|
||||
break // 如果不需要重试,跳出重试循环
|
||||
}
|
||||
}
|
||||
resultChan <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// 等待所有线程完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(resultChan)
|
||||
}()
|
||||
|
||||
// 检查结果
|
||||
for err := range resultChan {
|
||||
if err != nil {
|
||||
tmperr = err
|
||||
|
||||
if Common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-starttime > (int64(len(Common.Userdict["zabbix"])*len(Common.Passwords)) * Common.Timeout) {
|
||||
if retryErr := Common.CheckErrs(err); retryErr != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmperr
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
FROM mysql:latest
|
||||
|
||||
# 设置环境变量
|
||||
ENV MYSQL_ROOT_PASSWORD=123456
|
||||
ENV MYSQL_ROOT_PASSWORD=Password
|
||||
ENV MYSQL_DATABASE=mydb
|
||||
|
||||
# 开放3306端口
|
||||
|
@ -1,5 +1,2 @@
|
||||
docker build -t mysql-server .
|
||||
docker run -d \
|
||||
-p 3306:3306 \
|
||||
--name mysql-container \
|
||||
mysql-server
|
||||
docker run -d -p 3306:3306 --name mysql-container mysql-server
|
Loading…
x
Reference in New Issue
Block a user