This commit is contained in:
DVK 2023-02-24 20:32:28 +08:00 committed by GitHub
commit 2b9831486d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 180 additions and 265 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea/
result.txt

View File

@ -4,53 +4,25 @@ import (
"fmt"
"github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
type FtpConn struct{}
func FtpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
flag, err := FtpConn(info, "anonymous", "")
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v", info.Host, info.Ports, "anonymous", err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
}
for _, user := range common.Userdict["ftp"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := FtpConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
// 这里把单独的未授权访问测试:anonymous 添加到字典内来测试。
ftpConn := &FtpConn{}
bt := common.InitBruteThread("ftp", info, common.Timeout, ftpConn)
return bt.Run()
}
func FtpConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func (f *FtpConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(common.Timeout)*time.Second)
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(timeout)*time.Second)
if err == nil {
err = conn.Login(Username, Password)
if err == nil {

View File

@ -5,45 +5,28 @@ import (
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
type MssqlConn struct{}
func MssqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["mssql"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := MssqlConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] mssql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
mssqlConn := &MssqlConn{}
bt := common.InitBruteThread("mssql", info, common.Timeout, mssqlConn)
return bt.Run()
}
func MssqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func (m *MssqlConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(common.Timeout)*time.Second)
db, err := sql.Open("mssql", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()

View File

@ -5,45 +5,28 @@ import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
type MysqlConn struct{}
func MysqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["mysql"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := MysqlConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] mysql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
mysqlConn := &MysqlConn{}
bt := common.InitBruteThread("mysql", info, common.Timeout, mysqlConn)
return bt.Run()
}
func MysqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func (m *MysqlConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(common.Timeout)*time.Second)
db, err := sql.Open("mysql", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()

View File

@ -5,45 +5,28 @@ import (
"fmt"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
"strings"
"time"
)
type OracleConn struct{}
func OracleScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["oracle"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := OracleConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
oracleConn := &OracleConn{}
bt := common.InitBruteThread("oracle", info, common.Timeout, oracleConn)
return bt.Run()
}
func OracleConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func (o *OracleConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%s/orcl", Username, Password, Host, Port)
db, err := sql.Open("oracle", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
db.SetMaxIdleConns(0)
defer db.Close()
err = db.Ping()

View File

@ -5,44 +5,27 @@ import (
"fmt"
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
type PostgresConn struct{}
func PostgresScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["postgresql"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", string(user), -1)
flag, err := PostgresConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] psql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
postgresConn := &PostgresConn{}
bt := common.InitBruteThread("postgresql", info, common.Timeout, postgresConn)
return bt.Run()
}
func PostgresConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func (p *PostgresConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host, Port, "postgres", "disable")
db, err := sql.Open("postgres", dataSourceName)
if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
defer db.Close()
err = db.Ping()
if err == nil {

View File

@ -16,88 +16,27 @@ import (
"log"
"os"
"strconv"
"strings"
"sync"
"time"
)
type Brutelist struct {
user string
pass string
type RdpConn struct {
}
func RdpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
rdpConn := &RdpConn{}
bt := common.InitBruteThread("rdp", info, common.Timeout, rdpConn)
return bt.Run()
}
var wg sync.WaitGroup
var signal bool
var num = 0
var all = len(common.Userdict["rdp"]) * len(common.Passwords)
var mutex sync.Mutex
brlist := make(chan Brutelist, all)
func (r RdpConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, e error) {
port, _ := strconv.Atoi(info.Ports)
for _, user := range common.Userdict["rdp"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
brlist <- Brutelist{user, pass}
}
}
for i := 0; i < common.BruteThread; i++ {
wg.Add(1)
go worker(info.Host, common.Domain, port, &wg, brlist, &signal, &num, all, &mutex, common.Timeout)
}
close(brlist)
go func() {
wg.Wait()
signal = true
}()
for !signal {
}
return tmperr
}
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 == true {
return
}
go incrNum(num, mutex)
user, pass := one.user, one.pass
flag, err := RdpConn(host, domain, user, pass, port, timeout)
if flag == true && 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
} else {
errlog := fmt.Sprintf("[-] (%v/%v) rdp %v:%v %v %v %v", *num, all, host, port, user, pass, err)
common.LogError(errlog)
}
}
}
func incrNum(num *int, mutex *sync.Mutex) {
mutex.Lock()
*num = *num + 1
mutex.Unlock()
}
func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool, error) {
target := fmt.Sprintf("%s:%d", ip, port)
target := fmt.Sprintf("%s:%d", info.Host, port)
g := NewClient(target, glog.NONE)
err := g.Login(domain, user, password, timeout)
err := g.Login(common.Domain, user, pass, timeout)
if err == nil {
return true, nil

View File

@ -2,46 +2,21 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/stacktitan/smb/smb"
"strings"
"time"
)
type SmbConn struct {
}
func SmbScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return nil
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["smb"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := doWithTimeOut(info, user, pass)
if flag == true && err == nil {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, common.Domain, user, pass)
} else {
result = fmt.Sprintf("[+] SMB:%v:%v:%v %v", info.Host, info.Ports, user, pass)
}
common.LogSuccess(result)
return err
} else {
errlog := fmt.Sprintf("[-] smb %v:%v %v %v %v", info.Host, 445, user, pass, err)
errlog = strings.Replace(errlog, "\n", "", -1)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
}
}
return tmperr
smbConn := &SmbConn{}
bt := common.InitBruteThread("smb", info, common.Timeout, smbConn)
return bt.Run()
}
func SmblConn(info *common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) {
@ -67,7 +42,7 @@ func SmblConn(info *common.HostInfo, user string, pass string, signal chan struc
return flag, err
}
func doWithTimeOut(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func (s *SmbConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
signal := make(chan struct{})
go func() {
flag, err = SmblConn(info, user, pass, signal)
@ -75,7 +50,7 @@ func doWithTimeOut(info *common.HostInfo, user string, pass string) (flag bool,
select {
case <-signal:
return flag, err
case <-time.After(time.Duration(common.Timeout) * time.Second):
case <-time.After(time.Duration(timeout) * time.Second):
return false, errors.New("time out")
}
}

View File

@ -7,41 +7,22 @@ import (
"golang.org/x/crypto/ssh"
"io/ioutil"
"net"
"strings"
"time"
)
type SshConn struct {
}
func SshScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
starttime := time.Now().Unix()
for _, user := range common.Userdict["ssh"] {
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := SshConn(info, user, pass)
if flag == true && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ssh %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
common.LogError(errlog)
tmperr = err
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * common.Timeout) {
return err
}
}
if common.SshKey != "" {
return err
}
}
}
return tmperr
sshConn := &SshConn{}
bt := common.InitBruteThread("ssh", info, common.Timeout, sshConn)
return bt.Run()
}
func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func (*SshConn) Attack(info *common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
Auth := []ssh.AuthMethod{}
@ -62,7 +43,7 @@ func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err er
config := &ssh.ClientConfig{
User: Username,
Auth: Auth,
Timeout: time.Duration(common.Timeout) * time.Second,
Timeout: time.Duration(timeout) * time.Second,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},

114
common/Brute.go Normal file
View File

@ -0,0 +1,114 @@
package common
import (
"fmt"
"strings"
"sync"
"time"
)
// 多线程暴力破解模块
type BruteList struct {
user string
pass string
}
type BruteFunc interface {
Attack(info *HostInfo, user string, pass string, timeout int64) (flag bool, err error)
}
type BruteThreader struct {
wg sync.WaitGroup
mutex sync.Mutex
signal bool
num int
bruteType string
bruteFunc BruteFunc
info *HostInfo
timeout int64
}
func InitBruteThread(bruteType string, info *HostInfo, timeout int64, bruteFunc BruteFunc) (b *BruteThreader) {
bt := &BruteThreader{
num: 0,
bruteType: bruteType,
bruteFunc: bruteFunc,
info: info,
timeout: timeout,
}
return bt
}
func (t *BruteThreader) Run() (tmperr error) {
brList, total := t.generateData()
for i := 0; i < BruteThread; i++ {
t.wg.Add(1)
go t.worker(brList, total)
}
close(brList)
go func() {
t.wg.Wait()
t.signal = true
}()
for !t.signal {
}
return tmperr
}
func (t *BruteThreader) generateData() (data chan BruteList, total int) {
var all = len(Userdict[t.bruteType]) * len(Passwords)
brList := make(chan BruteList, all)
for _, user := range Userdict[t.bruteType] {
for _, pass := range Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
brList <- BruteList{user, pass}
}
}
return brList, all
}
func (t *BruteThreader) worker(brList chan BruteList, all int) (tmperr error) {
defer t.wg.Done()
starttime := time.Now().Unix()
for one := range brList {
if t.signal == true {
return
}
go t.incrNum(&t.num, &t.mutex)
user, pass := one.user, one.pass
flag, err := t.bruteFunc.Attack(t.info, user, pass, t.timeout)
if flag == true && err == nil {
var result string
if Domain != "" {
result = fmt.Sprintf("[+] %v:%v:%v:%v\\%v %v", t.bruteType, t.info.Host, t.info.Ports, Domain, user, pass)
} else {
result = fmt.Sprintf("[+] %v:%v:%v:%v %v", t.bruteType, t.info.Host, t.info.Ports, user, pass)
}
LogSuccess(result)
t.signal = true
return
} else {
errlog := fmt.Sprintf("[-] (%v/%v) %v %v:%v %v %v %v", t.num, all, t.bruteType, t.info.Host, t.info.Ports, user, pass, err)
LogError(errlog)
tmperr = err
if CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(all) * t.timeout) {
return err
}
}
}
return
}
func (t *BruteThreader) incrNum(num *int, mutex *sync.Mutex) {
mutex.Lock()
*num = *num + 1
mutex.Unlock()
}

View File

@ -2,7 +2,7 @@ package common
var version = "1.8.2"
var Userdict = map[string][]string{
"ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"},
"ftp": {"anonymous", "ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"},
"mysql": {"root", "mysql"},
"mssql": {"sa", "sql"},
"smb": {"administrator", "admin", "guest"},