refactor: 输出格式重构,去掉所有插件的多线程,因为多线程会导致结果不准确,加入进度条

This commit is contained in:
ZacharyZcR
2025-01-01 07:18:36 +08:00
parent 277ea5d332
commit ceede3cd68
49 changed files with 1448 additions and 2911 deletions
+41 -86
View File
@@ -5,7 +5,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"net"
"strings"
"sync"
"time"
)
@@ -16,7 +15,6 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 首先测试默认账户
for retryCount := 0; retryCount < maxRetries; retryCount++ {
@@ -35,103 +33,60 @@ func ActiveMQScan(info *Common.HostInfo) (tmperr error) {
break
}
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["activemq"])*len(Common.Passwords))
starttime := time.Now().Unix()
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()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行连接测试
done := make(chan struct {
success bool
err error
})
// 执行连接测试
done := make(chan struct {
go func(user, pass string) {
flag, err := ActiveMQConn(info, user, pass)
done <- struct {
success bool
err error
})
}{flag, err}
}(user, pass)
go func(user, pass string) {
flag, err := ActiveMQConn(info, user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success {
return nil
}
if err != nil {
errlog := fmt.Sprintf("ActiveMQ服务 %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
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
if err != nil {
errlog := fmt.Sprintf("ActiveMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue
}
}
break
}
}
}
@@ -171,7 +126,7 @@ func ActiveMQConn(info *Common.HostInfo, user string, pass string) (bool, error)
response := string(respBuf[:n])
if strings.Contains(response, "CONNECTED") {
result := fmt.Sprintf("[+] ActiveMQ服务 %v:%v 爆破成功 用户名: %v 密码: %v",
result := fmt.Sprintf("ActiveMQ服务 %v:%v 爆破成功 用户名: %v 密码: %v",
info.Host, info.Ports, user, pass)
Common.LogSuccess(result)
return true, nil
+42 -87
View File
@@ -6,7 +6,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"strconv"
"strings"
"sync"
"time"
)
@@ -16,7 +15,6 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
// 首先测试无认证访问
@@ -34,103 +32,60 @@ func CassandraScan(info *Common.HostInfo) (tmperr error) {
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)
// 启动工作线程
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
}
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
// 执行连接
done := make(chan struct {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行连接
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}
}(user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Cassandra服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+12 -12
View File
@@ -541,7 +541,7 @@ func (d *DomainInfo) GetSPNs() (map[string][]string, error) {
_ = entry.GetAttributeValue("cn")
spnList := entry.GetAttributeValues("servicePrincipalName")
if len(spnList) > 0 {
key := fmt.Sprintf("[*] SPN%s", dn)
key := fmt.Sprintf("SPN%s", dn)
spns[key] = spnList
}
}
@@ -708,7 +708,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
for _, category := range categories {
if computers, ok := specialComputers[category]; ok {
fmt.Printf("[*] %s:\n", category)
fmt.Printf("%s:\n", category)
for _, computer := range computers {
fmt.Printf("\t%s\n", computer)
}
@@ -724,7 +724,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
}
// 打印用户信息
fmt.Println("[*] 域用户:")
fmt.Println("域用户:")
for _, user := range users {
fmt.Println("\t" + user)
}
@@ -737,7 +737,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
}
// 打印域管理员信息
fmt.Println("[*] 域管理员:")
fmt.Println("域管理员:")
for _, admin := range admins {
fmt.Println("\t" + admin)
}
@@ -750,7 +750,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
}
// 打印组织单位信息
fmt.Println("[*] 组织单位:")
fmt.Println("组织单位:")
for _, ou := range ous {
fmt.Println("\t" + ou)
}
@@ -763,7 +763,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
}
// 打印域计算机信息
fmt.Println("[*] 域计算机:")
fmt.Println("域计算机:")
for _, computer := range computers {
fmt.Printf("\t%s", computer.Name)
if computer.OperatingSystem != "" {
@@ -775,7 +775,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
// 获取并显示信任域关系
trustDomains, err := di.GetTrustDomains()
if err == nil {
fmt.Println("[*] 信任域关系:")
fmt.Println("信任域关系:")
for _, domain := range trustDomains {
fmt.Printf("\t%s\n", domain)
}
@@ -786,7 +786,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
adminGroups, err := di.GetAdminGroups()
if err == nil {
for groupName, members := range adminGroups {
fmt.Printf("[*] %s成员:\n", groupName)
fmt.Printf("%s成员:\n", groupName)
for _, member := range members {
fmt.Printf("\t%s\n", member)
}
@@ -798,7 +798,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
delegations, err := di.GetDelegation()
if err == nil {
for delegationType, entries := range delegations {
fmt.Printf("[*] %s:\n", delegationType)
fmt.Printf("%s:\n", delegationType)
for _, entry := range entries {
fmt.Printf("\t%s\n", entry)
}
@@ -809,7 +809,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
// 获取并显示AS-REP Roasting漏洞用户
asrepUsers, err := di.GetAsrepRoastUsers()
if err == nil {
fmt.Println("[*] AS-REP弱口令账户:")
fmt.Println("AS-REP弱口令账户:")
for _, user := range asrepUsers {
fmt.Printf("\t%s\n", user)
}
@@ -819,7 +819,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
// 获取并显示域密码策略
passwordPolicy, err := di.GetPasswordPolicy()
if err == nil {
fmt.Println("[*] 域密码策略:")
fmt.Println("域密码策略:")
for key, value := range passwordPolicy {
fmt.Printf("\t%s: %s\n", key, value)
}
@@ -843,7 +843,7 @@ func DCInfoScan(info *Common.HostInfo) (err error) {
fmt.Println()
}
} else {
fmt.Println("[*] 未发现SPN信息\n")
fmt.Println("未发现SPN信息\n")
}
return nil
}
+42 -87
View File
@@ -7,7 +7,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"net/http"
"strings"
"sync"
"time"
)
@@ -18,7 +17,6 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 首先测试无认证访问
for retryCount := 0; retryCount < maxRetries; retryCount++ {
@@ -35,105 +33,62 @@ func ElasticScan(info *Common.HostInfo) (tmperr error) {
break
}
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["elastic"])*len(Common.Passwords))
starttime := time.Now().Unix()
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()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行连接尝试
done := make(chan struct {
success bool
err error
})
// 执行连接尝试
done := make(chan struct {
go func(user, pass string) {
flag, err := ElasticConn(info, user, pass)
done <- struct {
success bool
err error
})
}{flag, err}
}(user, pass)
go func(user, pass string) {
flag, err := ElasticConn(info, user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Elasticsearch服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+49 -139
View File
@@ -1,12 +1,10 @@
package Plugins
import (
"context"
"fmt"
"github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/Common"
"strings"
"sync"
"time"
)
@@ -17,11 +15,6 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 创建带取消功能的context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 先尝试匿名登录
for retryCount := 0; retryCount < maxRetries; retryCount++ {
@@ -29,152 +22,74 @@ func FtpScan(info *Common.HostInfo) (tmperr error) {
if flag && err == nil {
return nil
}
errlog := fmt.Sprintf("ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v", info.Host, info.Ports, "anonymous", err)
Common.LogError(errlog)
if err != nil && !strings.Contains(err.Error(), "Login incorrect") {
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue
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))
starttime := time.Now().Unix()
// 任务分发goroutine
go func() {
defer close(taskChan)
for _, user := range Common.Userdict["ftp"] {
for _, pass := range Common.Passwords {
select {
case <-ctx.Done():
return
default:
pass = strings.Replace(pass, "{user}", user, -1)
taskChan <- struct {
user string
pass string
}{user, pass}
}
// 遍历所有用户名密码组合
for _, user := range Common.Userdict["ftp"] {
for _, pass := range Common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
}
}()
var wg sync.WaitGroup
resultChan := make(chan error, threads)
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行FTP连接
done := make(chan struct {
success bool
err error
})
// 启动工作线程
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for task := range taskChan {
select {
case <-ctx.Done():
resultChan <- nil
return
default:
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
done := make(chan struct {
go func(user, pass string) {
success, err := FtpConn(info, user, pass)
done <- struct {
success bool
err error
}, 1)
}{success, err}
}(user, pass)
connCtx, connCancel := context.WithTimeout(ctx, time.Duration(Common.Timeout)*time.Second)
go func(user, pass string) {
success, err := FtpConn(info, user, pass)
select {
case <-connCtx.Done():
case done <- struct {
success bool
err error
}{success, err}:
}
}(task.user, task.pass)
var err error
select {
case <-ctx.Done():
connCancel()
resultChan <- nil
return
case result := <-done:
err = result.err
if result.success && err == nil {
successLog := fmt.Sprintf("FTP %v:%v %v %v",
info.Host, info.Ports, task.user, task.pass)
Common.LogSuccess(successLog)
time.Sleep(100 * time.Millisecond)
cancel() // 取消所有操作
resultChan <- nil
return
}
case <-connCtx.Done():
err = fmt.Errorf("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
connCancel()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("[-] ftp %v:%v %v %v %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
if err != nil {
select {
case <-ctx.Done():
resultChan <- nil
return
default:
}
errlog := fmt.Sprintf("ftp %v:%v %v %v %v",
info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog)
if strings.Contains(err.Error(), "Login incorrect") {
break
}
if strings.Contains(err.Error(), "too many connections") {
time.Sleep(5 * time.Second)
if retryCount < maxRetries-1 {
continue
}
}
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
continue
}
continue
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
break
}
}
resultChan <- nil
}()
}
go func() {
wg.Wait()
close(resultChan)
}()
for err := range resultChan {
if err != nil {
tmperr = err
if !strings.Contains(err.Error(), "扫描超时") {
if retryErr := Common.CheckErrs(err); retryErr != nil {
continue
}
break // 如果不需要重试,跳出重试循环
}
}
}
@@ -191,12 +106,6 @@ func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
if err != nil {
return false, err
}
// 确保连接被关闭
defer func() {
if conn != nil {
conn.Quit() // 发送QUIT命令关闭连接
}
}()
// 尝试登录
if err = conn.Login(Username, Password); err != nil {
@@ -204,7 +113,7 @@ func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
}
// 登录成功,获取目录信息
result := fmt.Sprintf("ftp %v:%v:%v %v", Host, Port, Username, Password)
result := fmt.Sprintf("[+] ftp %v:%v:%v %v", Host, Port, Username, Password)
dirs, err := conn.List("")
if err == nil && len(dirs) > 0 {
// 最多显示前6个目录
@@ -217,5 +126,6 @@ func FtpConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
}
}
Common.LogSuccess(result)
return true, nil
}
+6 -6
View File
@@ -71,14 +71,14 @@ func FcgiScan(info *Common.HostInfo) error {
}
}()
if err != nil {
fmt.Printf("[-] FastCGI连接失败 %v:%v - %v\n", info.Host, info.Ports, err)
fmt.Printf("FastCGI连接失败 %v:%v - %v\n", info.Host, info.Ports, err)
return err
}
// 发送FastCGI请求
stdout, stderr, err := fcgi.Request(env, reqParams)
if err != nil {
fmt.Printf("[-] FastCGI请求失败 %v:%v - %v\n", info.Host, info.Ports, err)
fmt.Printf("FastCGI请求失败 %v:%v - %v\n", info.Host, info.Ports, err)
return err
}
@@ -90,10 +90,10 @@ func FcgiScan(info *Common.HostInfo) error {
// 命令执行成功,提取输出结果
output = strings.SplitN(output, cutLine, 2)[0]
if len(stderr) > 0 {
result = fmt.Sprintf("[+] FastCGI漏洞确认 %v:%v\n命令输出:\n%v\n错误信息:\n%v\n建议尝试其他路径,例如: -path /www/wwwroot/index.php",
result = fmt.Sprintf("FastCGI漏洞确认 %v:%v\n命令输出:\n%v\n错误信息:\n%v\n建议尝试其他路径,例如: -path /www/wwwroot/index.php",
info.Host, info.Ports, output, string(stderr))
} else {
result = fmt.Sprintf("[+] FastCGI漏洞确认 %v:%v\n命令输出:\n%v",
result = fmt.Sprintf("FastCGI漏洞确认 %v:%v\n命令输出:\n%v",
info.Host, info.Ports, output)
}
Common.LogSuccess(result)
@@ -102,10 +102,10 @@ func FcgiScan(info *Common.HostInfo) error {
strings.Contains(output, "Status") {
// 目标存在FastCGI服务但可能路径错误
if len(stderr) > 0 {
result = fmt.Sprintf("[*] FastCGI服务确认 %v:%v\n响应:\n%v\n错误信息:\n%v\n建议尝试其他路径,例如: -path /www/wwwroot/index.php",
result = fmt.Sprintf("FastCGI服务确认 %v:%v\n响应:\n%v\n错误信息:\n%v\n建议尝试其他路径,例如: -path /www/wwwroot/index.php",
info.Host, info.Ports, output, string(stderr))
} else {
result = fmt.Sprintf("[*] FastCGI服务确认 %v:%v\n响应:\n%v",
result = fmt.Sprintf("FastCGI服务确认 %v:%v\n响应:\n%v",
info.Host, info.Ports, output)
}
Common.LogSuccess(result)
+4 -4
View File
@@ -149,12 +149,12 @@ func read(text []byte, host string) error {
}
// 构建基础结果
result := fmt.Sprintf("[*] NetInfo 扫描结果")
result += fmt.Sprintf("\n[*] 目标主机: %s", host)
result := fmt.Sprintf("NetInfo 扫描结果")
result += fmt.Sprintf("\n目标主机: %s", host)
if name != "" {
result += fmt.Sprintf("\n[*] 主机名: %s", name)
result += fmt.Sprintf("\n主机名: %s", name)
}
result += "\n[*] 发现的网络接口:"
result += "\n发现的网络接口:"
// 用于分类存储地址
var ipv4Addrs []string
+41 -83
View File
@@ -8,7 +8,6 @@ import (
"io"
"net"
"strings"
"sync"
"time"
)
@@ -18,102 +17,61 @@ func IMAPScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
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)
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行IMAP连接
done := make(chan struct {
success bool
err error
})
// 执行IMAP连接
done := make(chan struct {
go func(user, pass string) {
success, err := IMAPConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
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
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("IMAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue
}
}
break
}
}
}
+42 -88
View File
@@ -5,18 +5,15 @@ import (
"github.com/IBM/sarama"
"github.com/shadow1ng/fscan/Common"
"strings"
"sync"
"time"
)
// KafkaScan 执行 Kafka 服务扫描
func KafkaScan(info *Common.HostInfo) (tmperr error) {
if Common.DisableBrute {
return
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 首先测试无认证访问
for retryCount := 0; retryCount < maxRetries; retryCount++ {
@@ -33,105 +30,62 @@ func KafkaScan(info *Common.HostInfo) (tmperr error) {
break
}
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["kafka"])*len(Common.Passwords))
starttime := time.Now().Unix()
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行Kafka连接
done := make(chan struct {
success bool
err error
})
// 执行Kafka连接
done := make(chan struct {
go func(user, pass string) {
success, err := KafkaConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Kafka服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+42 -87
View File
@@ -5,7 +5,6 @@ import (
"github.com/go-ldap/ldap/v3"
"github.com/shadow1ng/fscan/Common"
"strings"
"sync"
"time"
)
@@ -16,7 +15,6 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 首先尝试匿名访问
flag, err := LDAPConn(info, "", "")
@@ -24,105 +22,62 @@ func LDAPScan(info *Common.HostInfo) (tmperr error) {
return err
}
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["ldap"])*len(Common.Passwords))
starttime := time.Now().Unix()
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行LDAP连接
done := make(chan struct {
success bool
err error
})
// 执行LDAP连接
done := make(chan struct {
go func(user, pass string) {
success, err := LDAPConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("LDAP服务 %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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("LDAP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+5 -5
View File
@@ -89,10 +89,10 @@ var (
)
func LocalInfoScan(info *Common.HostInfo) (err error) {
fmt.Println("[+] LocalInfo扫描模块开始...")
fmt.Println("LocalInfo扫描模块开始...")
home, err := os.UserHomeDir()
if err != nil {
errlog := fmt.Sprintf("[-] Get UserHomeDir error: %v", err)
errlog := fmt.Sprintf("Get UserHomeDir error: %v", err)
Common.LogError(errlog)
return err
}
@@ -103,7 +103,7 @@ func LocalInfoScan(info *Common.HostInfo) (err error) {
// 规则搜索
searchSensitiveFiles()
fmt.Println("[+] LocalInfo扫描模块结束...")
fmt.Println("LocalInfo扫描模块结束...")
return nil
}
@@ -148,7 +148,7 @@ func scanFixedLocations(home string) {
func checkAndLogFile(path string) {
if _, err := os.Stat(path); err == nil {
result := fmt.Sprintf("[+] Found sensitive file: %s", path)
result := fmt.Sprintf("Found sensitive file: %s", path)
Common.LogSuccess(result)
}
}
@@ -202,7 +202,7 @@ func searchSensitiveFiles() {
for _, white := range whitelist {
fileName := strings.ToLower(info.Name())
if strings.Contains(fileName, white) {
result := fmt.Sprintf("[+] Found potential sensitive file: %s", path)
result := fmt.Sprintf("Found potential sensitive file: %s", path)
Common.LogSuccess(result)
break
}
+42 -85
View File
@@ -6,7 +6,6 @@ import (
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/Common"
"strings"
"sync"
"time"
)
@@ -17,103 +16,61 @@ func MssqlScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
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)
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行MSSQL连接
done := make(chan struct {
success bool
err error
})
// 执行MSSQL连接
done := make(chan struct {
go func(user, pass string) {
success, err := MssqlConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
go func() {
wg.Wait()
close(resultChan)
}()
if err != nil {
errlog := fmt.Sprintf("MSSQL %v:%v %v %v %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
@@ -150,7 +107,7 @@ func MssqlConn(info *Common.HostInfo, user string, pass string) (bool, error) {
}
// 连接成功
result := fmt.Sprintf("[+] MSSQL %v:%v:%v %v", host, port, username, password)
result := fmt.Sprintf("MSSQL %v:%v:%v %v", host, port, username, password)
Common.LogSuccess(result)
return true, nil
}
+52 -113
View File
@@ -6,7 +6,6 @@ import (
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/Common"
"strings"
"sync"
"time"
)
@@ -17,132 +16,72 @@ func MysqlScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
// 添加成功标志通道
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 检查是否已经成功
select {
case <-successChan:
resultChan <- nil
return
default:
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行MySQL连接
done := make(chan struct {
success bool
err error
})
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 执行MySQL连接
done := make(chan struct {
go func(user, pass string) {
success, err := MysqlConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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 // 如果不需要重试,跳出重试循环
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
// 连接成功
successLog := fmt.Sprintf("MySQL %v:%v %v %v",
info.Host, info.Ports, user, pass)
Common.LogSuccess(successLog)
return nil
}
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("MySQL %v:%v %v %v %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if !strings.Contains(err.Error(), "Access denied") {
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 特殊处理认证失败的情况
if strings.Contains(err.Error(), "Access denied") {
break // 跳出重试循环,继续下一个密码
}
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
tmperr = err
if !strings.Contains(err.Error(), "Access denied") {
return err
}
}
continue // 继续重试
}
break // 如果不需要重试,跳出重试循环
}
}
}
+42 -87
View File
@@ -5,7 +5,6 @@ import (
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
"github.com/shadow1ng/fscan/Common"
"strings"
"sync"
"time"
)
@@ -16,7 +15,6 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 首先测试无认证访问和默认凭证
initialChecks := []struct {
@@ -34,105 +32,62 @@ func Neo4jScan(info *Common.HostInfo) (tmperr error) {
}
}
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["neo4j"])*len(Common.Passwords))
starttime := time.Now().Unix()
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()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行Neo4j连接
done := make(chan struct {
success bool
err error
})
// 执行Neo4j连接
done := make(chan struct {
go func(user, pass string) {
flag, err := Neo4jConn(info, user, pass)
done <- struct {
success bool
err error
})
}{flag, err}
}(user, pass)
go func(user, pass string) {
flag, err := Neo4jConn(info, user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Neo4j服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+1 -1
View File
@@ -229,7 +229,7 @@ func (info *NetBiosInfo) String() (output string) {
}
if text == "" {
} else if info.DomainControllers != "" {
output = fmt.Sprintf("[+] DC:%-24s", text)
output = fmt.Sprintf("DC:%-24s", text)
} else {
output = fmt.Sprintf("%-30s", text)
}
+42 -88
View File
@@ -6,7 +6,6 @@ import (
"github.com/shadow1ng/fscan/Common"
_ "github.com/sijms/go-ora/v2"
"strings"
"sync"
"time"
)
@@ -17,107 +16,62 @@ func OracleScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
// 创建任务通道
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行Oracle连接
done := make(chan struct {
success bool
err error
})
// 执行Oracle连接
done := make(chan struct {
go func(user, pass string) {
success, err := OracleConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Oracle %v:%v %v %v %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+46 -92
View File
@@ -7,7 +7,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"net"
"strings"
"sync"
"time"
)
@@ -17,111 +16,66 @@ func POP3Scan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
// 创建任务通道
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行POP3连接
done := make(chan struct {
success bool
err error
})
// 执行POP3连接
done := make(chan struct {
go func(user, pass string) {
success, err := POP3Conn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
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, user, pass)
Common.LogSuccess(successLog)
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("POP3服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+42 -88
View File
@@ -6,7 +6,6 @@ import (
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/Common"
"strings"
"sync"
"time"
)
@@ -17,107 +16,62 @@ func PostgresScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
// 创建任务通道
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行PostgreSQL连接
done := make(chan struct {
success bool
err error
})
// 执行PostgreSQL连接
done := make(chan struct {
go func(user, pass string) {
success, err := PostgresConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("PostgreSQL %v:%v %v %v %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+23 -113
View File
@@ -37,130 +37,40 @@ func RdpScan(info *Common.HostInfo) (tmperr error) {
return
}
var (
wg sync.WaitGroup
num = 0
all = len(Common.Userdict["rdp"]) * len(Common.Passwords)
mutex sync.Mutex
)
// 创建任务通道和结果通道
brlist := make(chan Brutelist)
resultChan := make(chan bool)
port, _ := strconv.Atoi(info.Ports)
total := len(Common.Userdict["rdp"]) * len(Common.Passwords)
num := 0
// 启动工作协程
for i := 0; i < Common.BruteThreads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for one := range brlist {
select {
case <-resultChan: // 检查是否已经找到有效凭据
return
default:
// 遍历用户名密码组合
for _, user := range Common.Userdict["rdp"] {
for _, pass := range Common.Passwords {
num++
pass = strings.Replace(pass, "{user}", user, -1)
// 尝试连接
flag, err := RdpConn(info.Host, Common.Domain, user, pass, port, Common.Timeout)
if flag && err == nil {
// 连接成功
var result string
if Common.Domain != "" {
result = fmt.Sprintf("RDP %v:%v:%v\\%v %v", info.Host, port, Common.Domain, user, pass)
} else {
result = fmt.Sprintf("RDP %v:%v:%v %v", info.Host, port, user, pass)
}
mutex.Lock()
num++
mutex.Unlock()
user, pass := one.user, one.pass
flag, err := RdpConn(info.Host, Common.Domain, user, pass, port, Common.Timeout)
if flag && err == nil {
// 连接成功
var result string
if Common.Domain != "" {
result = fmt.Sprintf("RDP %v:%v:%v\\%v %v", info.Host, port, Common.Domain, user, pass)
} else {
result = fmt.Sprintf("RDP %v:%v:%v %v", info.Host, port, user, pass)
}
Common.LogSuccess(result)
select {
case resultChan <- true: // 通知其他goroutine找到了有效凭据
default:
}
return
}
// 连接失败
errlog := fmt.Sprintf("(%v/%v) RDP %v:%v %v %v %v", num, all, info.Host, port, user, pass, err)
Common.LogError(errlog)
Common.LogSuccess(result)
return nil
}
}()
}
// 分发扫描任务
go func() {
for _, user := range Common.Userdict["rdp"] {
for _, pass := range Common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
select {
case <-resultChan: // 如果已经找到有效凭据,停止分发任务
return
case brlist <- Brutelist{user, pass}:
}
}
// 连接失败
errlog := fmt.Sprintf("(%v/%v) RDP %v:%v %v %v %v", num, total, info.Host, port, user, pass, err)
Common.LogError(errlog)
}
close(brlist)
}()
// 等待任务完成或找到有效凭据
go func() {
wg.Wait()
close(resultChan)
}()
// 等待结果
if <-resultChan {
return nil
}
return tmperr
}
// worker RDP扫描工作协程
func worker(host, domain string, port int, wg *sync.WaitGroup, brlist chan Brutelist,
signal *bool, num *int, all int, mutex *sync.Mutex, timeout int64) {
defer wg.Done()
for one := range brlist {
if *signal {
return
}
go incrNum(num, mutex)
user, pass := one.user, one.pass
flag, err := RdpConn(host, domain, user, pass, port, timeout)
if flag && err == nil {
// 连接成功
var result string
if domain != "" {
result = fmt.Sprintf("RDP %v:%v:%v\\%v %v", host, port, domain, user, pass)
} else {
result = fmt.Sprintf("RDP %v:%v:%v %v", host, port, user, pass)
}
Common.LogSuccess(result)
*signal = true
return
}
// 连接失败
errlog := fmt.Sprintf("(%v/%v) RDP %v:%v %v %v %v", *num, all, host, port, user, pass, err)
Common.LogError(errlog)
}
}
// incrNum 线程安全地增加计数器
func incrNum(num *int, mutex *sync.Mutex) {
mutex.Lock()
*num++
mutex.Unlock()
}
// RdpConn 尝试RDP连接
func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool, error) {
defer func() {
+91 -94
View File
@@ -6,7 +6,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"net"
"strings"
"sync"
"time"
)
@@ -17,116 +16,114 @@ func RabbitMQScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["rabbitmq"])*len(Common.Passwords)+1) // +1 是为了加入guest账号
// 先测试默认账号 guest/guest
user, pass := "guest", "guest"
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
resultChan := make(chan error, threads)
// 执行RabbitMQ连接
done := make(chan struct {
success bool
err error
})
// 先加入默认账号guest/guest
taskChan <- struct {
user string
pass string
}{"guest", "guest"}
go func() {
success, err := RabbitMQConn(info, user, pass)
done <- struct {
success bool
err error
}{success, err}
}()
// 生成其他用户名密码组合任务
// 等待结果或超时
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, user, pass)
Common.LogSuccess(result)
return nil
}
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, user, pass, err)
Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue
}
}
break
}
// 遍历其他用户名密码组合
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行RabbitMQ连接
done := make(chan struct {
success bool
err error
})
// 执行RabbitMQ连接
done := make(chan struct {
go func(user, pass string) {
success, err := RabbitMQConn(info, user, pass)
done <- struct {
success bool
err error
})
}{success, err}
}(user, pass)
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("连接超时")
// 等待结果或超时
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, user, pass)
Common.LogSuccess(result)
return nil
}
// 处理错误情况
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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
if err != nil {
errlog := fmt.Sprintf("RabbitMQ服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue
}
}
break
}
}
}
+6 -6
View File
@@ -489,10 +489,10 @@ func readreply(conn net.Conn) (string, error) {
// testwrite 测试Redis写入权限
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
fmt.Println("[*] 开始测试Redis写入权限...")
fmt.Println("开始测试Redis写入权限...")
// 测试SSH目录写入权限
fmt.Println("[*] 正在测试 /root/.ssh/ 目录写入权限...")
fmt.Println("正在测试 /root/.ssh/ 目录写入权限...")
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
if err != nil {
fmt.Printf("发送SSH目录测试命令失败: %v\n", err)
@@ -503,7 +503,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
fmt.Printf("读取SSH目录测试响应失败: %v\n", err)
return flag, flagCron, err
}
fmt.Printf("[*] SSH目录测试响应: %s\n", text)
fmt.Printf("SSH目录测试响应: %s\n", text)
if strings.Contains(text, "OK") {
flag = true
fmt.Println("SSH目录写入权限测试成功")
@@ -512,7 +512,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
}
// 测试定时任务目录写入权限
fmt.Println("[*] 正在测试 /var/spool/cron/ 目录写入权限...")
fmt.Println("正在测试 /var/spool/cron/ 目录写入权限...")
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
if err != nil {
fmt.Printf("发送定时任务目录测试命令失败: %v\n", err)
@@ -523,7 +523,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
fmt.Printf("读取定时任务目录测试响应失败: %v\n", err)
return flag, flagCron, err
}
fmt.Printf("[*] 定时任务目录测试响应: %s\n", text)
fmt.Printf("定时任务目录测试响应: %s\n", text)
if strings.Contains(text, "OK") {
flagCron = true
fmt.Println("定时任务目录写入权限测试成功")
@@ -531,7 +531,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
fmt.Println("定时任务目录写入权限测试失败")
}
fmt.Printf("[*] 写入权限测试完成 - SSH权限: %v, Cron权限: %v\n", flag, flagCron)
fmt.Printf("写入权限测试完成 - SSH权限: %v, Cron权限: %v\n", flag, flagCron)
return flag, flagCron, err
}
+42 -87
View File
@@ -5,7 +5,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"net"
"strings"
"sync"
"time"
)
@@ -16,7 +15,6 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 首先测试匿名访问
for retryCount := 0; retryCount < maxRetries; retryCount++ {
@@ -36,105 +34,62 @@ func RsyncScan(info *Common.HostInfo) (tmperr error) {
break
}
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["rsync"])*len(Common.Passwords))
starttime := time.Now().Unix()
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()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行Rsync连接
done := make(chan struct {
success bool
err error
})
// 执行Rsync连接
done := make(chan struct {
go func(user, pass string) {
flag, err := RsyncConn(info, user, pass)
done <- struct {
success bool
err error
})
}{flag && err == nil, err}
}(user, pass)
go func(user, pass string) {
flag, err := RsyncConn(info, user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success {
return nil
}
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Rsync服务 %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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Rsync服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+23 -68
View File
@@ -5,7 +5,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"github.com/stacktitan/smb/smb"
"strings"
"sync"
"time"
)
@@ -14,83 +13,39 @@ func SmbScan(info *Common.HostInfo) (tmperr error) {
return nil
}
threads := Common.BruteThreads
var wg sync.WaitGroup
successChan := make(chan struct{}, 1)
// 按用户分组处理
// 遍历所有用户
for _, user := range Common.Userdict["smb"] {
taskChan := make(chan string, len(Common.Passwords))
// 遍历该用户的所有密码
for _, pass := range Common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
taskChan <- pass
}
close(taskChan)
for i := 0; i < threads; i++ {
wg.Add(1)
go func(username string) {
defer wg.Done()
for pass := range taskChan {
select {
case <-successChan:
return
default:
}
success, err := doWithTimeOut(info, username, pass)
if success {
if Common.Domain != "" {
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s\\%s:%s",
info.Host, info.Ports, Common.Domain, username, pass))
} else {
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s:%s",
info.Host, info.Ports, username, pass))
}
successChan <- struct{}{}
// 成功后等待确保日志打印完成
time.Sleep(500 * time.Millisecond)
return
}
if err != nil {
Common.LogError(fmt.Sprintf("SMB认证失败 %s:%s %s:%s %v",
info.Host, info.Ports, username, pass, err))
// 等待失败日志打印完成
time.Sleep(100 * time.Millisecond)
if strings.Contains(err.Error(), "账号锁定") {
for range taskChan {
// 清空通道
}
time.Sleep(200 * time.Millisecond) // 确保锁定日志打印完成
return
}
}
success, err := doWithTimeOut(info, user, pass)
if success {
if Common.Domain != "" {
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s\\%s:%s",
info.Host, info.Ports, Common.Domain, user, pass))
} else {
Common.LogSuccess(fmt.Sprintf("SMB认证成功 %s:%s %s:%s",
info.Host, info.Ports, user, pass))
}
}(user)
}
return nil
}
wg.Wait()
if err != nil {
Common.LogError(fmt.Sprintf("SMB认证失败 %s:%s %s:%s %v",
info.Host, info.Ports, user, pass, err))
select {
case <-successChan:
// 等待日志打印完成
time.Sleep(500 * time.Millisecond)
Common.LogWG.Wait()
return nil
default:
// 等待失败日志打印完成
time.Sleep(100 * time.Millisecond)
if strings.Contains(err.Error(), "账号锁定") {
// 账号锁定时跳过当前用户的剩余密码
break // 跳出密码循环,继续下一个用户
}
}
}
}
// 主函数结束前多等待一会
time.Sleep(500 * time.Millisecond)
Common.LogWG.Wait()
// 最后再等待一下,确保所有日志都打印完成
time.Sleep(500 * time.Millisecond)
return nil
}
+64 -161
View File
@@ -6,7 +6,6 @@ import (
"net"
"os"
"strings"
"sync"
"time"
"github.com/hirochachacha/go-smb2"
@@ -27,110 +26,59 @@ func SmbScan2(info *Common.HostInfo) (tmperr error) {
return smbPasswordScan(info)
}
// smbPasswordScan 使用密码进行认证扫描
func smbPasswordScan(info *Common.HostInfo) error {
if Common.DisableBrute {
return nil
}
threads := Common.BruteThreads
var wg sync.WaitGroup
successChan := make(chan struct{}, 1)
hasprint := false
var hasPrintMutex sync.Mutex
// 改成按用户分组处理
// 遍历每个用户
for _, user := range Common.Userdict["smb"] {
// 为每个用户创建密码任务通道
taskChan := make(chan string, len(Common.Passwords))
// 生成该用户的所有密码任务
// 遍历该用户的所有密码
for _, pass := range Common.Passwords {
pass = strings.ReplaceAll(pass, "{user}", user)
taskChan <- pass
}
close(taskChan)
// 启动工作线程
for i := 0; i < threads; i++ {
wg.Add(1)
go func(username string) {
defer wg.Done()
// 重试循环
for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
success, err, printed := Smb2Con(info, user, pass, []byte{}, hasprint)
for pass := range taskChan {
select {
case <-successChan:
return
default:
time.Sleep(100 * time.Millisecond)
}
if printed {
hasprint = true
}
// 重试循环
for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
hasPrintMutex.Lock()
currentHasPrint := hasprint
hasPrintMutex.Unlock()
if success {
logSuccessfulAuth(info, user, pass, []byte{})
return nil
}
success, err, printed := Smb2Con(info, username, pass, []byte{}, currentHasPrint)
if err != nil {
logFailedAuth(info, user, pass, []byte{}, err)
if printed {
hasPrintMutex.Lock()
hasprint = true
hasPrintMutex.Unlock()
time.Sleep(100 * time.Millisecond)
}
if success {
logSuccessfulAuth(info, username, pass, []byte{})
time.Sleep(100 * time.Millisecond)
successChan <- struct{}{}
return
}
if err != nil {
logFailedAuth(info, username, pass, []byte{}, err)
time.Sleep(100 * time.Millisecond)
// 检查是否账户锁定
if strings.Contains(err.Error(), "user account has been automatically locked") {
// 发现账户锁定,清空任务通道并返回
for range taskChan {
// 清空通道
}
return
}
// 其他登录失败情况
if strings.Contains(err.Error(), "LOGIN_FAILED") ||
strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "attempted logon is invalid") ||
strings.Contains(err.Error(), "bad username or authentication") {
break
}
if retryCount < Common.MaxRetries-1 {
time.Sleep(time.Second * time.Duration(retryCount+2))
continue
}
}
// 检查是否账户锁定
if strings.Contains(err.Error(), "user account has been automatically locked") {
// 账户锁定,跳过该用户的剩余密码
break
}
// 其他登录失败情况
if strings.Contains(err.Error(), "LOGIN_FAILED") ||
strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "attempted logon is invalid") ||
strings.Contains(err.Error(), "bad username or authentication") {
break
}
if retryCount < Common.MaxRetries-1 {
time.Sleep(time.Second * time.Duration(retryCount+2))
continue
}
}
}(user)
}
wg.Wait() // 等待当前用户的所有密码尝试完成
// 检查是否已经找到正确密码
select {
case <-successChan:
return nil
default:
break
}
}
}
time.Sleep(200 * time.Millisecond)
return nil
}
@@ -139,94 +87,49 @@ func smbHashScan(info *Common.HostInfo) error {
return nil
}
threads := Common.BruteThreads
var wg sync.WaitGroup
successChan := make(chan struct{}, 1)
hasprint := false
var hasPrintMutex sync.Mutex
// 按用户分组处理
// 遍历每个用户
for _, user := range Common.Userdict["smb"] {
// 为每个用户创建hash任务通道
taskChan := make(chan []byte, len(Common.HashBytes))
// 生成该用户的所有hash任务
// 遍历该用户的所有hash
for _, hash := range Common.HashBytes {
taskChan <- hash
}
close(taskChan)
// 重试循环
for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
success, err, printed := Smb2Con(info, user, "", hash, hasprint)
// 启动工作线程
for i := 0; i < threads; i++ {
wg.Add(1)
go func(username string) {
defer wg.Done()
if printed {
hasprint = true
}
for hash := range taskChan {
select {
case <-successChan:
return
default:
}
if success {
logSuccessfulAuth(info, user, "", hash)
return nil
}
// 重试循环
for retryCount := 0; retryCount < Common.MaxRetries; retryCount++ {
hasPrintMutex.Lock()
currentHasPrint := hasprint
hasPrintMutex.Unlock()
if err != nil {
logFailedAuth(info, user, "", hash, err)
success, err, printed := Smb2Con(info, username, "", hash, currentHasPrint)
if printed {
hasPrintMutex.Lock()
hasprint = true
hasPrintMutex.Unlock()
}
if success {
logSuccessfulAuth(info, username, "", hash)
successChan <- struct{}{}
return
}
if err != nil {
logFailedAuth(info, username, "", hash, err)
// 检查是否账户锁定
if strings.Contains(err.Error(), "user account has been automatically locked") {
// 发现账户锁定,清空任务通道并返回
for range taskChan {
// 清空通道
}
return
}
// 其他登录失败情况
if strings.Contains(err.Error(), "LOGIN_FAILED") ||
strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "attempted logon is invalid") ||
strings.Contains(err.Error(), "bad username or authentication") {
break
}
if retryCount < Common.MaxRetries-1 {
time.Sleep(time.Second * time.Duration(retryCount+1))
continue
}
}
// 检查是否账户锁定
if strings.Contains(err.Error(), "user account has been automatically locked") {
// 账户锁定,跳过该用户的剩余hash
break
}
// 其他登录失败情况
if strings.Contains(err.Error(), "LOGIN_FAILED") ||
strings.Contains(err.Error(), "Authentication failed") ||
strings.Contains(err.Error(), "attempted logon is invalid") ||
strings.Contains(err.Error(), "bad username or authentication") {
break
}
if retryCount < Common.MaxRetries-1 {
time.Sleep(time.Second * time.Duration(retryCount+1))
continue
}
}
}(user)
}
wg.Wait() // 等待当前用户的所有hash尝试完成
// 检查是否已经找到正确凭据
select {
case <-successChan:
return nil
default:
break
}
}
}
+42 -87
View File
@@ -6,7 +6,6 @@ import (
"net"
"net/smtp"
"strings"
"sync"
"time"
)
@@ -17,7 +16,6 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 先测试匿名访问
for retryCount := 0; retryCount < maxRetries; retryCount++ {
@@ -36,105 +34,62 @@ func SmtpScan(info *Common.HostInfo) (tmperr error) {
break
}
// 创建任务通道
taskChan := make(chan struct {
user string
pass string
}, len(Common.Userdict["smtp"])*len(Common.Passwords))
starttime := time.Now().Unix()
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()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行SMTP连接
done := make(chan struct {
success bool
err error
})
// 执行SMTP连接
done := make(chan struct {
go func(user, pass string) {
flag, err := SmtpConn(info, user, pass)
done <- struct {
success bool
err error
})
}{flag, err}
}(user, pass)
go func(user, pass string) {
flag, err := SmtpConn(info, user, pass)
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("连接超时")
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success && err == nil {
return nil
}
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("SMTP服务 %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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("SMTP服务 %v:%v 尝试失败 用户名: %v 密码: %v 错误: %v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
+50 -91
View File
@@ -6,7 +6,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"strconv"
"strings"
"sync"
"time"
)
@@ -17,106 +16,66 @@ func SNMPScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
portNum, _ := strconv.Atoi(info.Ports)
defaultCommunities := []string{"public", "private", "cisco", "community"}
starttime := time.Now().Unix()
timeout := time.Duration(Common.Timeout) * time.Second
// 创建任务通道
taskChan := make(chan string, len(defaultCommunities))
resultChan := make(chan error, threads)
// 生成所有community任务
// 遍历所有 community
for _, community := range defaultCommunities {
taskChan <- community
}
close(taskChan)
// 检查是否超时
if time.Now().Unix()-starttime > int64(timeout.Seconds()) {
return fmt.Errorf("扫描超时")
}
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行SNMP连接
done := make(chan struct {
success bool
err error
})
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
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)
return nil
}
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)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
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)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
resultChan <- err
return
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
continue // 继续重试
}
}
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
}
break // 如果不需要重试,跳出重试循环
}
}
+52 -98
View File
@@ -1,13 +1,13 @@
package Plugins
import (
"context"
"fmt"
"github.com/shadow1ng/fscan/Common"
"golang.org/x/crypto/ssh"
"io/ioutil"
"net"
"strings"
"sync"
"time"
)
@@ -17,97 +17,67 @@ func SshScan(info *Common.HostInfo) (tmperr error) {
}
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)
// 生成所有任务
// 遍历所有用户名密码组合
for _, user := range Common.Userdict["ssh"] {
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()
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
done := make(chan struct {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(Common.Timeout)*time.Second)
done := make(chan struct {
success bool
err error
}, 1)
go func(user, pass string) {
success, err := SshConn(info, user, pass)
select {
case <-ctx.Done():
case done <- struct {
success bool
err error
})
go func(user, pass string) {
success, err := SshConn(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 {
resultChan <- nil
return
}
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}{success, err}:
}
}(user, pass)
if err != nil {
errlog := fmt.Sprintf("SSH认证失败 %v:%v User:%v Pass:%v Err:%v",
info.Host, info.Ports, task.user, task.pass, err)
Common.LogError(errlog)
// 检查是否是已知错误,如果是则等待3秒后重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
resultChan <- err
return
}
continue // 继续重试
}
var err error
select {
case result := <-done:
err = result.err
if result.success {
successLog := fmt.Sprintf("SSH认证成功 %v:%v User:%v Pass:%v",
info.Host, info.Ports, user, pass)
Common.LogSuccess(successLog)
time.Sleep(100 * time.Millisecond)
cancel()
return nil
}
if Common.SshKeyPath != "" {
resultChan <- err
return
}
break // 如果不需要重试,跳出重试循环
case <-ctx.Done():
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
go func() {
wg.Wait()
close(resultChan)
}()
cancel()
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
if err != nil {
errlog := fmt.Sprintf("SSH认证失败 %v:%v User:%v Pass:%v Err:%v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue
}
}
if Common.SshKeyPath != "" {
return err
}
break
}
}
}
@@ -153,29 +123,13 @@ func SshConn(info *Common.HostInfo, user string, pass string) (flag bool, err er
}
defer session.Close()
flag = true
// 如果需要执行命令
if Common.Command != "" {
output, err := session.CombinedOutput(Common.Command)
_, err := session.CombinedOutput(Common.Command)
if err != nil {
return true, err
}
if Common.SshKeyPath != "" {
Common.LogSuccess(fmt.Sprintf("SSH密钥认证成功 %v:%v\n命令输出:\n%v",
info.Host, info.Ports, string(output)))
} else {
Common.LogSuccess(fmt.Sprintf("SSH认证成功 %v:%v User:%v Pass:%v\n命令输出:\n%v",
info.Host, info.Ports, user, pass, string(output)))
}
} else {
if Common.SshKeyPath != "" {
Common.LogSuccess(fmt.Sprintf("SSH密钥认证成功 %v:%v",
info.Host, info.Ports))
} else {
Common.LogSuccess(fmt.Sprintf("SSH认证成功 %v:%v User:%v Pass:%v",
info.Host, info.Ports, user, pass))
}
}
return flag, nil
return true, nil
}
+1 -1
View File
@@ -153,7 +153,7 @@ func SmbGhostScan(info *Common.HostInfo) error {
bytes.Equal(buff[74:76], []byte{0x02, 0x00}) {
// 发现漏洞,记录结果
result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
result := fmt.Sprintf("%v CVE-2020-0796 SmbGhost Vulnerable", ip)
Common.LogSuccess(result)
}
+53 -100
View File
@@ -8,7 +8,6 @@ import (
"net"
"regexp"
"strings"
"sync"
"time"
)
@@ -19,120 +18,74 @@ func TelnetScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
// 创建任务通道
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)
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
for task := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行Telnet连接
done := make(chan struct {
success bool
noAuth bool
err error
})
// 执行Telnet连接
done := make(chan struct {
go func(user, pass string) {
flag, err := telnetConn(info, user, pass)
done <- struct {
success bool
noAuth bool
err error
})
}{err == nil, flag, err}
}(user, pass)
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)
// 等待结果或超时
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)
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)
resultChan <- nil
return
}
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
// 等待结果或超时
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 result.success {
// 成功爆破
result := fmt.Sprintf("Telnet服务 %v:%v 用户名:%v 密码:%v",
info.Host, info.Ports, user, pass)
Common.LogSuccess(result)
return nil
}
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Telnet连接失败 %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 // 如果不需要重试,跳出重试循环
case <-time.After(time.Duration(Common.Timeout) * time.Second):
err = fmt.Errorf("连接超时")
}
}
resultChan <- nil
}()
}
// 等待所有线程完成
go func() {
wg.Wait()
close(resultChan)
}()
// 处理错误情况
if err != nil {
errlog := fmt.Sprintf("Telnet连接失败 %v:%v 用户名:%v 密码:%v 错误:%v",
info.Host, info.Ports, user, pass, err)
Common.LogError(errlog)
// 检查结果
for err := range resultChan {
if err != nil {
tmperr = err
if retryErr := Common.CheckErrs(err); retryErr != nil {
return err
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
}
}
-177
View File
@@ -1,177 +0,0 @@
package Plugins
import (
"crypto/tls"
"encoding/base64"
"fmt"
"github.com/shadow1ng/fscan/Common"
"net/http"
"strings"
"sync"
"time"
)
// TomcatScan 执行 Tomcat Manager 服务扫描
func TomcatScan(info *Common.HostInfo) (tmperr error) {
if Common.DisableBrute {
return
}
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)
// 启动工作线程
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
}
// 执行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 retryErr := Common.CheckErrs(err); retryErr != nil {
return err
}
}
}
return tmperr
}
// TomcatConn 尝试 Tomcat Manager 连接
func TomcatConn(info *Common.HostInfo, user string, pass string) (bool, error) {
host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second
client := &http.Client{
Timeout: timeout,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
// 尝试不同的管理路径
paths := []string{
"/manager/html",
"/manager/status",
"/manager/text",
"/host-manager/html",
}
for _, path := range paths {
baseURL := fmt.Sprintf("http://%s:%s%s", host, port, path)
req, err := http.NewRequest("GET", baseURL, nil)
if err != nil {
continue
}
// 添加Basic认证
auth := base64.StdEncoding.EncodeToString([]byte(user + ":" + pass))
req.Header.Add("Authorization", "Basic "+auth)
resp, err := client.Do(req)
if err != nil {
continue
}
defer resp.Body.Close()
// 检查响应状态
if resp.StatusCode == 200 {
result := fmt.Sprintf("[+] Tomcat Manager %v:%v %s 爆破成功 用户名: %v 密码: %v",
host, port, path, user, pass)
Common.LogSuccess(result)
return true, nil
}
}
return false, fmt.Errorf("认证失败")
}
+49 -89
View File
@@ -5,7 +5,6 @@ import (
"github.com/mitchellh/go-vnc"
"github.com/shadow1ng/fscan/Common"
"net"
"sync"
"time"
)
@@ -16,103 +15,64 @@ func VncScan(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
modename := "vnc"
starttime := time.Now().Unix()
// 创建任务通道
taskChan := make(chan string, len(Common.Passwords))
resultChan := make(chan error, threads)
// 生成所有密码任务
// 遍历所有密码
for _, pass := range Common.Passwords {
taskChan <- pass
}
close(taskChan)
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
// 启动工作线程
var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
defer wg.Done()
starttime := time.Now().Unix()
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行VNC连接
done := make(chan struct {
success bool
err error
})
for pass := range taskChan {
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
resultChan <- fmt.Errorf("扫描超时")
return
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)
return nil
}
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)
// 检查是否是需要重试的错误
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
// 执行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)
// 检查是否是需要重试的错误
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
resultChan <- err
return
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
continue // 继续重试
}
}
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
}
break // 如果不需要重试,跳出重试循环
}
}
+71 -115
View File
@@ -7,7 +7,6 @@ import (
"github.com/shadow1ng/fscan/Common"
"os"
"strings"
"sync"
"time"
)
@@ -34,130 +33,87 @@ func WmiExec(info *Common.HostInfo) (tmperr error) {
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
starttime := time.Now().Unix()
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)
taskChan <- struct {
user string
pass string
}{user, pass}
// 检查是否超时
if time.Now().Unix()-starttime > int64(Common.Timeout) {
return fmt.Errorf("扫描超时")
}
// 重试循环
for retryCount := 0; retryCount < maxRetries; retryCount++ {
// 执行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}
}(user, pass)
// 等待结果或超时
var err error
select {
case result := <-done:
err = result.err
if result.success {
// 成功连接
var successLog string
if Common.Domain != "" {
successLog = fmt.Sprintf("WmiExec %v:%v:%v\\%v ",
info.Host, info.Ports, Common.Domain, user)
} else {
successLog = fmt.Sprintf("WmiExec %v:%v:%v ",
info.Host, info.Ports, user)
}
if Common.HashValue != "" {
successLog += "hash: " + Common.HashValue
} else {
successLog += pass
}
Common.LogSuccess(successLog)
return nil
}
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, user, pass, err)
errlog = strings.Replace(errlog, "\n", "", -1)
Common.LogError(errlog)
// 检查是否需要重试
if retryErr := Common.CheckErrs(err); retryErr != nil {
if retryCount == maxRetries-1 {
return err
}
continue // 继续重试
}
}
break // 如果不需要重试,跳出重试循环
}
// 如果是32位hash值,只尝试一次密码
if len(Common.HashValue) == 32 {
break
}
}
}
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
}
// 执行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 != "" {
successLog = fmt.Sprintf("[+] WmiExec %v:%v:%v\\%v ",
info.Host, info.Ports, Common.Domain, task.user)
} else {
successLog = fmt.Sprintf("[+] WmiExec %v:%v:%v ",
info.Host, info.Ports, task.user)
}
if Common.HashValue != "" {
successLog += "hash: " + Common.HashValue
} else {
successLog += 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("[-] 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 // 继续重试
}
}
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
}
-209
View File
@@ -1,209 +0,0 @@
package Plugins
import (
"encoding/json"
"fmt"
"github.com/go-resty/resty/v2"
"github.com/shadow1ng/fscan/Common"
"net"
"strings"
"sync"
"time"
)
// ZabbixScan 执行 Zabbix 服务扫描
func ZabbixScan(info *Common.HostInfo) (tmperr error) {
if Common.DisableBrute {
return
}
maxRetries := Common.MaxRetries
threads := Common.BruteThreads
// 先测试默认账号
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)
// 启动工作线程
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
}
// 执行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 retryErr := Common.CheckErrs(err); retryErr != nil {
return err
}
}
}
return tmperr
}
// ZabbixConn 尝试 Zabbix API 连接
func ZabbixConn(info *Common.HostInfo, user string, pass string) (bool, error) {
host, port := info.Host, info.Ports
timeout := time.Duration(Common.Timeout) * time.Second
// 构造 API URL
apiURL := fmt.Sprintf("http://%s:%s/api_jsonrpc.php", host, port)
// 构造认证请求
authRequest := map[string]interface{}{
"jsonrpc": "2.0",
"method": "user.login",
"params": map[string]string{
"user": user,
"password": pass,
},
"id": 1,
}
// 创建HTTP客户端
client := resty.New()
client.SetTimeout(timeout)
// 发送认证请求
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(authRequest).
Post(apiURL)
if err != nil {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
return false, fmt.Errorf("连接超时")
}
return false, err
}
// 解析响应
var result struct {
Result string `json:"result"`
Error struct {
Code int `json:"code"`
Message string `json:"message"`
Data string `json:"data"`
} `json:"error"`
}
if err := json.Unmarshal(resp.Body(), &result); err != nil {
return false, fmt.Errorf("响应解析失败")
}
// 检查是否认证成功
if result.Result != "" {
success := fmt.Sprintf("[+] Zabbix服务 %v:%v 爆破成功 用户名: %v 密码: %v", host, port, user, pass)
Common.LogSuccess(success)
return true, nil
}
return false, fmt.Errorf("认证失败: %v", result.Error.Message)
}