├── README.md ├── common ├── ScanTask │ └── task.go ├── brute │ ├── brute.go │ ├── dic.go │ ├── ftp.go │ ├── mongo.go │ ├── mssql.go │ ├── mysql.go │ ├── postgres.go │ ├── redis.go │ ├── smb.go │ └── ssh.go ├── portscan │ ├── finger.go │ ├── icmp.go │ ├── identify.go │ ├── init.go │ ├── scan.go │ ├── send.go │ └── service.go └── util │ ├── config.go │ ├── output.go │ ├── rules.go │ └── util.go ├── config.yaml ├── go.mod ├── imgs ├── E3D2A0DF-9441-4099-9442-03374D62639E.png └── WechatIMG22.png └── main.go /README.md: -------------------------------------------------------------------------------- 1 | # Mscan 2 | 3 | ## 简介 4 | 5 | Mscan是一款基于go语言开发的内网资产探测工具,致力于帮企业梳理内部资产情况。 6 | 7 | ## 编译 8 | 9 | 项目基于golang 1.17版本进行开发,如需自行编译 10 | ```shell 11 | git clone https://github.com/mmM1ku/Mscan 12 | cd Mscan 13 | #m1 mac 14 | sudo CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -a -ldflags '-s -w --extldflags "-static -fpic"' -o mscan_darwin_arm64 15 | #intel mac 16 | sudo CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -a -ldflags '-s -w --extldflags "-static -fpic"' -o mscan_darwin_amd64 17 | #linux 18 | sudo CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -ldflags '-s -w --extldflags "-static -fpic"' -o mscan_linux_amd64 19 | #windows 20 | sudo CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -a -ldflags '-s -w --extldflags "-static -fpic"' -o mscan_windows_amd64.exe 21 | ``` 22 | 23 | ## 使用 24 | 25 | 端口扫描 26 | ```shell 27 | #指定端口扫描 28 | mscan -i 192.168.0.1/24,10.0.0.1-64 -p 22,80,8000-8010 -t 100 29 | #默认扫描top端口 30 | mscan -i 127.0.0.1 -t 100 31 | ``` 32 | 弱口令爆破 33 | ```shell 34 | #指定爆破模块 35 | mscan -i 127.0.0.1 -p 22 -m ssh -t 100 36 | #默认全协议爆破(需发现协议端口存在) 37 | mscan -i 127.0.0.1 -t 100 38 | ``` 39 | 结果输出 40 | ```shell 41 | #本地生成result.json 42 | mscan -i 127.0.0.1 -t 100 -o json 43 | ``` 44 | 参数说明 45 | ```shell 46 | mscan --help 47 | -i 指定ip地址,支持nmap写法 48 | -p 可选参数,指定端口,支持逗号,分隔符方式,例如80,443或者8000-8100 49 | -t 扫描线程数,默认50 50 | -u 用户名字典路径,不指定默认root,administrator 51 | -w 密码字典路径,不指定默认内部top100 52 | -o 输出方式,目前仅支持json输出 53 | ``` 54 | 55 | 56 | ## 运行截图 57 | ![运行截图](https://raw.githubusercontent.com/mmM1ku/Mscan/main/imgs/WechatIMG22.png "运行截图") 58 | 59 | ## 参考链接 60 | 61 | [fscan](https://github.com/shadow1ng/fscan) 62 | 63 | [Ladongo](https://github.com/k8gege/LadonGo) 64 | 65 | [Dismap](https://github.com/zhzyker/dismap) 66 | 67 | ## 感谢 68 | 69 | 感谢[FingerprintHub](https://github.com/0x727/FingerprintHub) 提供的指纹 70 | 71 | 72 | -------------------------------------------------------------------------------- /common/ScanTask/task.go: -------------------------------------------------------------------------------- 1 | package ScanTask 2 | 3 | import ( 4 | "Mscan/common/portscan" 5 | "Mscan/common/util" 6 | "github.com/kpango/glg" 7 | "sync" 8 | ) 9 | 10 | type Task struct { 11 | AddrList string 12 | PortList string 13 | Thread int 14 | Module string 15 | ScanResult []string 16 | Wg *sync.WaitGroup 17 | UserDicList []string 18 | PassDicList []string 19 | userpath string 20 | passpath string 21 | dicChan chan string 22 | bruteThread int 23 | lock *sync.Mutex 24 | BruteResult []util.Result 25 | bruteFinishChan chan int64 26 | Reuslt map[string]*util.DetailResult 27 | outputMode string 28 | } 29 | 30 | // NewTask 创建新扫描结构体对象,初始化 31 | func NewTask(addr, port string, thread int, module string, bruteThread int, userpath string, passpath string, output string) *Task { 32 | return &Task{ 33 | AddrList: addr, 34 | PortList: port, 35 | Thread: thread, 36 | Module: module, 37 | Wg: &sync.WaitGroup{}, 38 | bruteThread: bruteThread, 39 | lock: &sync.Mutex{}, 40 | userpath: userpath, 41 | passpath: passpath, 42 | outputMode: output, 43 | } 44 | 45 | } 46 | 47 | func (t *Task) Run() { 48 | //端口扫描 49 | t.Scan() 50 | //导出结果 51 | if t.outputMode != "" { 52 | glg.Log("[+]开始导出结果...") 53 | util.Output(t.outputMode, t.Reuslt) 54 | glg.Success("[+]结果已生成") 55 | } 56 | } 57 | 58 | func (t *Task) Scan() { 59 | glg.Info("[+]开始扫描") 60 | s := portscan.NewScan(t.AddrList, t.PortList, t.Thread, t.Wg, t.lock, t.Module) 61 | t.Reuslt = s.ScanPool() 62 | s.BruteResult.Range(func(key, value interface{}) bool { 63 | target := key.(string) 64 | vul := value.(string) 65 | glg.Warnf("[!]%s存在 %s", target, vul) 66 | return true 67 | }) 68 | glg.Success("[+]扫描已完成") 69 | } 70 | -------------------------------------------------------------------------------- /common/brute/brute.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "Mscan/common/util" 5 | "sync" 6 | ) 7 | 8 | type Brute struct { 9 | bruteModule string 10 | bruteThread int 11 | bruteDic []Dic 12 | ftpDic []Dic 13 | mssqlDic []Dic 14 | mysqlDic []Dic 15 | postgresDic []Dic 16 | smbDic []Dic 17 | sshDic []Dic 18 | targetChan chan util.Target 19 | BruteResult sync.Map 20 | } 21 | 22 | func NewBrute(module string, thread int, target chan util.Target) *Brute { 23 | return &Brute{ 24 | bruteModule: module, 25 | bruteThread: thread, 26 | targetChan: target, 27 | } 28 | } 29 | 30 | func (b *Brute) BrutePool() { 31 | //init 32 | b.genDic() 33 | var wg = &sync.WaitGroup{} 34 | workChan := make(chan struct{}, 10) 35 | for target := range b.targetChan { 36 | target := target 37 | wg.Add(1) 38 | workChan <- struct{}{} 39 | go func() { 40 | switch target.Service { 41 | case "ssh": 42 | b.sshBrute(target.Target) 43 | case "ftp": 44 | b.ftpBrute(target.Target) 45 | case "redis": 46 | b.redisBrute(target.Target) 47 | case "mysql": 48 | b.mysqlBrute(target.Target) 49 | case "mongodb": 50 | b.mongoBrute(target.Target) 51 | case "microsoft-ds": 52 | b.smbBrute(target.Target) 53 | case "netbios-ssn": 54 | b.smbBrute(target.Target) 55 | case "postgresql": 56 | b.postgresqlBrute(target.Target) 57 | case "ms-sql-s": 58 | b.mssqlBrute(target.Target) 59 | } 60 | wg.Done() 61 | <-workChan 62 | }() 63 | } 64 | wg.Wait() 65 | close(workChan) 66 | } 67 | -------------------------------------------------------------------------------- /common/brute/dic.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import "Mscan/common/util" 4 | 5 | type Dic struct { 6 | User string 7 | Pwd string 8 | } 9 | 10 | func (b *Brute) genDic() { 11 | /*var dics []Dic 12 | for _, username := range util.UserList { 13 | for _, pwd := range util.PassList { 14 | dics = append(dics, Dic{username, pwd}) 15 | } 16 | } 17 | return dics*/ 18 | //ftp 19 | for _, username := range util.FtpUser { 20 | for _, pwd := range util.FtpPwd { 21 | b.ftpDic = append(b.ftpDic, Dic{username, pwd}) 22 | } 23 | } 24 | //mssql 25 | for _, username := range util.MssqlUser { 26 | for _, pwd := range util.MssqlPwd { 27 | b.mssqlDic = append(b.mssqlDic, Dic{username, pwd}) 28 | } 29 | } 30 | //mysql 31 | for _, username := range util.MysqlUser { 32 | for _, pwd := range util.MysqlPwd { 33 | b.mysqlDic = append(b.mysqlDic, Dic{username, pwd}) 34 | } 35 | } 36 | //postgres 37 | for _, username := range util.PostgresUser { 38 | for _, pwd := range util.PostgresPwd { 39 | b.postgresDic = append(b.postgresDic, Dic{username, pwd}) 40 | } 41 | } 42 | //smb 43 | for _, username := range util.SmbUser { 44 | for _, pwd := range util.SmbPwd { 45 | b.smbDic = append(b.smbDic, Dic{username, pwd}) 46 | } 47 | } 48 | //ssh 49 | for _, username := range util.SshUser { 50 | for _, pwd := range util.SshPwd { 51 | b.sshDic = append(b.sshDic, Dic{username, pwd}) 52 | } 53 | } 54 | } 55 | 56 | /* todo 字典文件读取 */ 57 | -------------------------------------------------------------------------------- /common/brute/ftp.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "Mscan/common/util" 5 | "github.com/jlaffaye/ftp" 6 | "github.com/kpango/glg" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | type FTP struct { 12 | addr []string 13 | thread int 14 | wg *sync.WaitGroup 15 | Result util.Result 16 | ResultSlice []util.Result 17 | lock *sync.Mutex 18 | workerChan chan struct{} 19 | Finish int64 20 | total int64 21 | dicchan *chan string 22 | userdic *[]string 23 | passdic *[]string 24 | } 25 | 26 | func ftpUnauth(addr string) bool { 27 | c, err := ftp.Dial(addr, ftp.DialWithTimeout(3*time.Second)) 28 | if err != nil { 29 | return false 30 | } 31 | err = c.Login("anonymous", "anonymous") 32 | if err != nil { 33 | return false 34 | } 35 | defer c.Logout() 36 | return true 37 | } 38 | 39 | func ftpCon(addr, user, pass string) error { 40 | c, err := ftp.Dial(addr, ftp.DialWithTimeout(3*time.Second)) 41 | if err != nil { 42 | return err 43 | } 44 | err = c.Login(user, pass) 45 | if err != nil { 46 | return err 47 | } 48 | defer c.Logout() 49 | return nil 50 | } 51 | 52 | func (b *Brute) ftpBrute(target string) { 53 | var wg = &sync.WaitGroup{} 54 | workChan := make(chan struct{}, 10) 55 | if ftpUnauth(target) { 56 | glg.Warnf("[+]%s存在ftp匿名登录", target) 57 | b.BruteResult.Store(target, "ftp匿名登录") 58 | } else { 59 | for _, dic := range b.ftpDic { 60 | wg.Add(1) 61 | workChan <- struct{}{} 62 | dic := dic 63 | go func() { 64 | if err := ftpCon(target, dic.User, dic.Pwd); err == nil { 65 | glg.Warnf("[!]%s存在ftp弱口令%s/%s", target, dic.User, dic.Pwd) 66 | b.BruteResult.Store(target, "ftp弱口令:"+dic.User+"/"+dic.Pwd) 67 | } 68 | wg.Done() 69 | <-workChan 70 | }() 71 | } 72 | } 73 | wg.Wait() 74 | glg.Infof("[+]%s的ftp爆破已完成", target) 75 | close(workChan) 76 | } 77 | -------------------------------------------------------------------------------- /common/brute/mongo.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/kpango/glg" 7 | "go.mongodb.org/mongo-driver/mongo" 8 | "go.mongodb.org/mongo-driver/mongo/options" 9 | "go.mongodb.org/mongo-driver/mongo/readpref" 10 | ) 11 | 12 | func MongoUnauthCon(addr string) bool { 13 | dataSource := fmt.Sprintf("mongodb://%v", addr) 14 | client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(dataSource)) 15 | if err != nil { 16 | //glg.Error(err) 17 | return false 18 | } 19 | defer func() { 20 | if err = client.Disconnect(context.TODO()); err != nil { 21 | glg.Error(err) 22 | } 23 | }() 24 | if err := client.Ping(context.TODO(), readpref.Primary()); err != nil { 25 | //glg.Error(err) 26 | return false 27 | } 28 | return true 29 | } 30 | 31 | func (b *Brute) mongoBrute(target string) { 32 | if MongoUnauthCon(target) { 33 | glg.Warnf("[!]%s 存在mongodb未授权漏洞", target) 34 | b.BruteResult.Store(target, "mongodb未授权访问") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/brute/mssql.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | _ "github.com/denisenkom/go-mssqldb" 7 | "github.com/kpango/glg" 8 | "strings" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | func mssqlCon(addr, user, pass string) error { 14 | addrstr := strings.Split(addr, ":") 15 | host := addrstr[0] 16 | port := addrstr[1] 17 | dataSource := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%v;encrypt=disable;timeout=%v", host, user, pass, port, 3*time.Second) 18 | db, err := sql.Open("sqlserver", dataSource) 19 | if err != nil { 20 | return err 21 | } else { 22 | db.SetConnMaxLifetime(3 * time.Second) 23 | db.SetConnMaxIdleTime(3 * time.Second) 24 | db.SetMaxIdleConns(0) 25 | defer db.Close() 26 | err = db.Ping() 27 | if err != nil { 28 | return err 29 | } 30 | } 31 | return nil 32 | } 33 | 34 | func (b *Brute) mssqlBrute(target string) { 35 | var wg = &sync.WaitGroup{} 36 | workChan := make(chan struct{}, 10) 37 | for _, dic := range b.mssqlDic { 38 | wg.Add(1) 39 | workChan <- struct{}{} 40 | dic := dic 41 | go func() { 42 | if err := mssqlCon(target, dic.User, dic.Pwd); err == nil { 43 | glg.Warnf("[!]%s存在mssql弱口令%s/%s", target, dic.User, dic.Pwd) 44 | b.BruteResult.Store(target, "mssql弱口令:"+dic.User+"/"+dic.Pwd) 45 | } 46 | wg.Done() 47 | <-workChan 48 | }() 49 | } 50 | wg.Wait() 51 | glg.Infof("[+]%s的mssql爆破已完成", target) 52 | close(workChan) 53 | } 54 | -------------------------------------------------------------------------------- /common/brute/mysql.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | _ "github.com/go-sql-driver/mysql" 7 | "github.com/kpango/glg" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | func (b *Brute) mysqlBrute(target string) { 13 | var wg = &sync.WaitGroup{} 14 | workChan := make(chan struct{}, 10) 15 | for _, dic := range b.mysqlDic { 16 | wg.Add(1) 17 | workChan <- struct{}{} 18 | dic := dic 19 | go func() { 20 | if err := mysqlCon(target, dic.User, dic.Pwd); err == nil { 21 | glg.Warnf("[!]%s存在mysql弱口令%s/%s", target, dic.User, dic.Pwd) 22 | b.BruteResult.Store(target, "mysql弱口令:"+dic.User+"/"+dic.Pwd) 23 | } 24 | wg.Done() 25 | <-workChan 26 | }() 27 | } 28 | wg.Wait() 29 | glg.Infof("[+]%s的mysql爆破已完成", target) 30 | close(workChan) 31 | } 32 | 33 | func mysqlCon(addr, user, pass string) error { 34 | dataSource := fmt.Sprintf("%v:%v@tcp(%v)/", user, pass, addr) 35 | db, err := sql.Open("mysql", dataSource) 36 | if err != nil { 37 | return err 38 | } else { 39 | db.SetConnMaxLifetime(3 * time.Second) 40 | db.SetConnMaxIdleTime(3 * time.Second) 41 | db.SetMaxIdleConns(0) 42 | defer db.Close() 43 | err = db.Ping() 44 | if err != nil { 45 | return err 46 | } 47 | } 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /common/brute/postgres.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "github.com/kpango/glg" 7 | _ "github.com/lib/pq" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | func postgresCon(addr, user, pass string) error { 13 | dataSource := fmt.Sprintf("postgres://%v:%v@%v/postgres?sslmode=disable", user, pass, addr) 14 | //fmt.Println(dataSource) 15 | db, err := sql.Open("postgres", dataSource) 16 | if err != nil { 17 | return err 18 | } else { 19 | db.SetConnMaxLifetime(3 * time.Second) 20 | db.SetConnMaxIdleTime(3 * time.Second) 21 | db.SetMaxIdleConns(0) 22 | defer db.Close() 23 | err = db.Ping() 24 | if err != nil { 25 | return err 26 | } 27 | } 28 | return nil 29 | } 30 | 31 | func postgresDefaultUser(addr string) bool { 32 | dataSource := fmt.Sprintf("postgres://%v@%v/postgres?sslmode=disable", "postgres", addr) 33 | db, err := sql.Open("postgres", dataSource) 34 | if err != nil { 35 | return false 36 | } else { 37 | db.SetConnMaxLifetime(3 * time.Second) 38 | db.SetConnMaxIdleTime(3 * time.Second) 39 | db.SetMaxIdleConns(0) 40 | defer db.Close() 41 | err = db.Ping() 42 | if err != nil { 43 | return false 44 | } 45 | } 46 | return true 47 | } 48 | 49 | func (b *Brute) postgresqlBrute(target string) { 50 | var wg = &sync.WaitGroup{} 51 | workChan := make(chan struct{}, 10) 52 | if postgresDefaultUser(target) { 53 | glg.Warnf("[+]%s存在默认用户postgres无密码登录!", target) 54 | b.BruteResult.Store(target, "postgres用户无密码登录") 55 | } else { 56 | for _, dic := range b.postgresDic { 57 | wg.Add(1) 58 | workChan <- struct{}{} 59 | dic := dic 60 | go func() { 61 | if err := postgresCon(target, dic.User, dic.Pwd); err == nil { 62 | glg.Warnf("[!]%s存在postgresql弱口令%s/%s", target, dic.User, dic.Pwd) 63 | b.BruteResult.Store(target, "postgresql弱口令:"+dic.User+"/"+dic.Pwd) 64 | } 65 | wg.Done() 66 | <-workChan 67 | }() 68 | } 69 | } 70 | wg.Wait() 71 | glg.Infof("[+]%s的postgres爆破已完成", target) 72 | close(workChan) 73 | } 74 | -------------------------------------------------------------------------------- /common/brute/redis.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "github.com/gomodule/redigo/redis" 5 | "github.com/kpango/glg" 6 | "net" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | func redisUnauth(addr string) bool { 12 | conn, err := tcpConn(addr) 13 | if err != nil { 14 | return false 15 | } 16 | msg := "*1\r\n$4\r\ninfo\r\n" 17 | _, err = conn.Write([]byte(msg)) 18 | if err != nil { 19 | return false 20 | } 21 | _ = conn.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) 22 | rep := make([]byte, 256) 23 | _, _ = conn.Read(rep) 24 | if conn != nil { 25 | _ = conn.Close() 26 | } 27 | if rep != nil { 28 | if strings.Contains(string(rep), "redis_version") { 29 | return true 30 | } 31 | } 32 | return false 33 | } 34 | 35 | func redisCon(addr string) error { 36 | client, err := redis.Dial("tcp", addr) 37 | if err != nil { 38 | return err 39 | } 40 | defer client.Close() 41 | if client.Err() != nil { 42 | return client.Err() 43 | } 44 | return nil 45 | } 46 | 47 | func (b *Brute) redisBrute(target string) { 48 | //test unauth 49 | if redisUnauth(target) { 50 | glg.Warnf("[!]%s 存在redis未授权漏洞", target) 51 | b.BruteResult.Store(target, "redis未授权访问") 52 | } 53 | } 54 | 55 | func tcpConn(target string) (net.Conn, error) { 56 | conn, err := net.DialTimeout("tcp", target, time.Duration(2)*time.Second) 57 | if err != nil { 58 | return nil, err 59 | } 60 | err = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second)) 61 | if err != nil { 62 | if conn != nil { 63 | _ = conn.Close() 64 | } 65 | return nil, err 66 | } 67 | return conn, nil 68 | } 69 | -------------------------------------------------------------------------------- /common/brute/smb.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "github.com/hirochachacha/go-smb2" 5 | "github.com/kpango/glg" 6 | "net" 7 | "sync" 8 | ) 9 | 10 | func smbCon(addr, user, pass string) error { 11 | conn, err := net.Dial("tcp", addr) 12 | if err != nil { 13 | return err 14 | } 15 | defer conn.Close() 16 | 17 | d := smb2.Dialer{ 18 | Initiator: &smb2.NTLMInitiator{ 19 | User: user, 20 | Password: pass, 21 | }, 22 | } 23 | s, err := d.Dial(conn) 24 | if err != nil { 25 | return err 26 | } 27 | defer s.Logoff() 28 | return nil 29 | } 30 | 31 | func smbUnauth(addr string) bool { 32 | conn, err := net.Dial("tcp", addr) 33 | if err != nil { 34 | return false 35 | } 36 | defer conn.Close() 37 | 38 | d := smb2.Dialer{ 39 | Initiator: &smb2.NTLMInitiator{ 40 | User: "guest", 41 | }, 42 | } 43 | s, err := d.Dial(conn) 44 | if err != nil { 45 | return false 46 | } 47 | defer s.Logoff() 48 | return true 49 | } 50 | 51 | func (b *Brute) smbBrute(target string) { 52 | var wg = &sync.WaitGroup{} 53 | workChan := make(chan struct{}, 10) 54 | if smbUnauth(target) { 55 | glg.Warnf("[+]%s存在smb匿名用户guest登录", target) 56 | b.BruteResult.Store(target, "smb匿名用户guest登录") 57 | } else { 58 | for _, dic := range b.smbDic { 59 | wg.Add(1) 60 | workChan <- struct{}{} 61 | dic := dic 62 | go func() { 63 | if err := smbCon(target, dic.User, dic.Pwd); err == nil { 64 | glg.Warnf("[+]%s存在smb弱口令%s/%s", target, dic.User, dic.Pwd) 65 | b.BruteResult.Store(target, "smb弱口令:"+dic.User+"/"+dic.Pwd) 66 | } 67 | wg.Done() 68 | <-workChan 69 | }() 70 | } 71 | } 72 | wg.Wait() 73 | glg.Infof("%s的smb爆破已完成", target) 74 | close(workChan) 75 | } 76 | -------------------------------------------------------------------------------- /common/brute/ssh.go: -------------------------------------------------------------------------------- 1 | package brute 2 | 3 | import ( 4 | "github.com/kpango/glg" 5 | "golang.org/x/crypto/ssh" 6 | "net" 7 | "sync" 8 | ) 9 | 10 | func sshCon(addr, user, pass string) (bool, error) { 11 | var state bool 12 | client, err := ssh.Dial("tcp", addr, &ssh.ClientConfig{ 13 | User: user, 14 | Auth: []ssh.AuthMethod{ 15 | ssh.Password(pass), 16 | }, 17 | //HostKeyCallback: modSsh.InsecureIgnoreHostKey(), 18 | HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { 19 | return nil 20 | }, 21 | //Timeout: 3 * time.Second, 22 | }) 23 | if err == nil { 24 | defer client.Close() 25 | session, err := client.NewSession() 26 | errRet := session.Run("echo OK") 27 | if err == nil && errRet == nil { 28 | session.Close() 29 | state = true 30 | } 31 | } else { 32 | return false, err 33 | } 34 | return state, nil 35 | } 36 | 37 | func (b *Brute) sshBrute(target string) { 38 | var wg = &sync.WaitGroup{} 39 | workChan := make(chan struct{}, 10) 40 | for _, dic := range b.sshDic { 41 | wg.Add(1) 42 | workChan <- struct{}{} 43 | dic := dic 44 | go func() { 45 | res, err := sshCon(target, dic.User, dic.Pwd) 46 | if err != nil { 47 | 48 | } 49 | if res { 50 | glg.Warnf("[!]%s存在ssh弱口令%s/%s", target, dic.User, dic.Pwd) 51 | b.BruteResult.Store(target, "ssh弱口令:"+dic.User+"/"+dic.Pwd) 52 | } 53 | wg.Done() 54 | <-workChan 55 | }() 56 | } 57 | wg.Wait() 58 | glg.Infof("[+]%s的ssh爆破已完成", target) 59 | close(workChan) 60 | } 61 | 62 | /*todo ssh 并发重试 */ 63 | -------------------------------------------------------------------------------- /common/portscan/finger.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "Mscan/common/util" 5 | "fmt" 6 | "github.com/kpango/glg" 7 | "io/ioutil" 8 | "net/http" 9 | "regexp" 10 | "strconv" 11 | "strings" 12 | "sync" 13 | ) 14 | 15 | func (s *Scan) identifyFinger() { 16 | var wg = &sync.WaitGroup{} 17 | for target := range s.targetChan { 18 | wg.Add(1) 19 | target := target 20 | ip := strings.Split(target, ":")[0] 21 | go func() { 22 | if strings.Contains(target, ":80") { 23 | url := "http://" + target 24 | s.lock.Lock() 25 | if s.Result[ip].WebInfo[url] == nil { 26 | s.Result[ip].WebInfo[url] = &util.WebResult{} 27 | } 28 | s.Result[ip].WebInfo[url].Finger = make([]string, 0) 29 | s.lock.Unlock() 30 | title, status, err := s.defaultClient(ip, url) 31 | if err == nil { 32 | s.lock.Lock() 33 | s.Result[ip].WebInfo[url].Title = title 34 | s.Result[ip].WebInfo[url].StatusCode = status 35 | s.lock.Unlock() 36 | } 37 | } else if strings.Contains(target, ":443") { 38 | url := "https://" + target 39 | s.lock.Lock() 40 | if s.Result[ip].WebInfo[url] == nil { 41 | s.Result[ip].WebInfo[url] = &util.WebResult{} 42 | } 43 | s.Result[ip].WebInfo[url].Finger = make([]string, 0) 44 | s.lock.Unlock() 45 | title, status, err := s.defaultClient(ip, url) 46 | if err == nil { 47 | s.lock.Lock() 48 | s.Result[ip].WebInfo[url].Title = title 49 | s.Result[ip].WebInfo[url].StatusCode = status 50 | s.lock.Unlock() 51 | } 52 | } else { 53 | url1 := "http://" + target 54 | s.lock.Lock() 55 | if s.Result[ip].WebInfo[url1] == nil { 56 | s.Result[ip].WebInfo[url1] = &util.WebResult{} 57 | } 58 | s.Result[ip].WebInfo[url1].Finger = make([]string, 0) 59 | s.lock.Unlock() 60 | title1, status1, err := s.defaultClient(ip, url1) 61 | if err == nil { 62 | s.lock.Lock() 63 | s.Result[ip].WebInfo[url1].Title = title1 64 | s.Result[ip].WebInfo[url1].StatusCode = status1 65 | s.lock.Unlock() 66 | } 67 | url2 := "https://" + target 68 | s.lock.Lock() 69 | if s.Result[ip].WebInfo[url2] == nil { 70 | s.Result[ip].WebInfo[url2] = &util.WebResult{} 71 | } 72 | s.Result[ip].WebInfo[url2].Finger = make([]string, 0) 73 | s.lock.Unlock() 74 | title2, status2, err := s.defaultClient(ip, url2) 75 | if err == nil { 76 | s.lock.Lock() 77 | s.Result[ip].WebInfo[url2].Title = title2 78 | s.Result[ip].WebInfo[url2].StatusCode = status2 79 | s.lock.Unlock() 80 | } 81 | } 82 | wg.Done() 83 | }() 84 | } 85 | wg.Wait() 86 | close(s.respData) 87 | } 88 | 89 | func (s *Scan) defaultClient(ip, url string) (string, string, error) { 90 | var respTitle string 91 | var headers []string 92 | var respHeaders string 93 | //var redirectUrl string 94 | client := util.Client() 95 | req, err := http.NewRequest("GET", url, nil) 96 | if err != nil { 97 | return "", "", err 98 | } 99 | resp, err := client.Do(req) 100 | if err != nil { 101 | return "", "", err 102 | } 103 | defer resp.Body.Close() 104 | //get statusCode 105 | respStatusCode := strconv.Itoa(resp.StatusCode) 106 | //get respBody 107 | body, _ := ioutil.ReadAll(resp.Body) 108 | respBody := string(body) 109 | //get respTitle 110 | re := regexp.MustCompile("(.*)") 111 | if len(re.FindStringSubmatch(respBody)) != 0 { 112 | if re.FindStringSubmatch(respBody)[1] != "" { 113 | respTitle = re.FindStringSubmatch(respBody)[1] 114 | } else { 115 | respTitle = "None" 116 | } 117 | } else { 118 | respTitle = "None" 119 | } 120 | //get respHeaders 121 | for header, values := range resp.Header { 122 | for _, value := range values { 123 | headers = append(headers, fmt.Sprintf("%s:%s", header, value)) 124 | } 125 | } 126 | 127 | for _, header := range headers { 128 | respHeaders += header + "," 129 | } 130 | var res = &util.HttpRes{Target: ip, Url: url, RespTitle: respTitle, RespStatusCode: respStatusCode, RespHeader: respHeaders, RespBody: respBody} 131 | s.respData <- res 132 | return respTitle, respStatusCode, nil 133 | } 134 | 135 | func (s *Scan) checkFinger() { 136 | var wg = &sync.WaitGroup{} 137 | for res := range s.respData { 138 | wg.Add(1) 139 | res := res 140 | go func() { 141 | for _, finger := range s.defaultFinger { 142 | //判断header 143 | if checkHeaders(res.RespHeader, finger.Headers) { 144 | s.lock.Lock() 145 | if s.Result[res.Target].WebInfo[res.Url].Finger == nil { 146 | glg.Error(res.Url, "slice nil") 147 | } else { 148 | s.Result[res.Target].WebInfo[res.Url].Finger = append(s.Result[res.Target].WebInfo[res.Url].Finger, finger.Name) 149 | } 150 | s.lock.Unlock() 151 | continue 152 | } 153 | if checkBody(res.RespBody, finger.Keyword) { 154 | s.lock.Lock() 155 | if s.Result[res.Target].WebInfo[res.Url].Finger == nil { 156 | glg.Error(res.Url, "slice nil") 157 | } else { 158 | s.Result[res.Target].WebInfo[res.Url].Finger = append(s.Result[res.Target].WebInfo[res.Url].Finger, finger.Name) 159 | } 160 | s.lock.Unlock() 161 | } 162 | } 163 | wg.Done() 164 | }() 165 | } 166 | wg.Wait() 167 | } 168 | -------------------------------------------------------------------------------- /common/portscan/icmp.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "github.com/kpango/glg" 5 | "os/exec" 6 | "runtime" 7 | "sync" 8 | ) 9 | 10 | func ping(addr string) bool { 11 | var cmd *exec.Cmd 12 | switch runtime.GOOS { 13 | //linux、mac ping 超时单位为s,windows为ms 14 | case "windows": 15 | cmd = exec.Command("ping", addr, "-n", "1", "-w", "3000") 16 | case "linux": 17 | cmd = exec.Command("ping", addr, "-c", "1", "-w", "3", "-W", "3") 18 | case "darwin": 19 | cmd = exec.Command("ping", addr, "-c", "1", "-W", "3") 20 | } 21 | if cmd == nil { 22 | return false 23 | } 24 | err := cmd.Run() 25 | if err != nil { 26 | return false 27 | } 28 | return true 29 | } 30 | 31 | func (s *Scan) hostScan() { 32 | var wg = &sync.WaitGroup{} 33 | workChan := make(chan struct{}, 10) 34 | for _, ip := range s.ipList { 35 | ip := ip 36 | wg.Add(1) 37 | workChan <- struct{}{} 38 | go func() { 39 | if ping(ip) { 40 | glg.Logf("[+]主机%s存活", ip) 41 | s.hostChan <- ip 42 | } 43 | <-workChan 44 | wg.Done() 45 | }() 46 | } 47 | wg.Wait() 48 | glg.Success("[+]存活探测已完成!") 49 | close(workChan) 50 | close(s.hostChan) 51 | } 52 | -------------------------------------------------------------------------------- /common/portscan/identify.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | ) 7 | 8 | func identifyHttp(reply []byte) bool { 9 | //for _, rep := range reply { 10 | check, _ := regexp.Match("^HTTP/\\d.\\d \\d*", reply) 11 | if check { 12 | return true 13 | } 14 | //} 15 | return false 16 | } 17 | 18 | func checkHeaders(respHeader, headerFinger string) bool { 19 | var result bool 20 | if headerFinger != "" { 21 | if strings.Contains(headerFinger, "|") { 22 | headers := strings.Split(headerFinger, "|") 23 | for _, header := range headers { 24 | if strings.Contains(respHeader, header) { 25 | result = true 26 | } else { 27 | result = false 28 | break 29 | } 30 | } 31 | } else { 32 | if strings.Contains(respHeader, headerFinger) { 33 | result = true 34 | } else { 35 | result = false 36 | } 37 | } 38 | } 39 | return result 40 | } 41 | 42 | func checkBody(respBody, bodyFinger string) bool { 43 | var result bool 44 | if bodyFinger != "" { 45 | if strings.Contains(bodyFinger, "|") { 46 | keywords := strings.Split(bodyFinger, "|") 47 | for _, keyword := range keywords { 48 | if strings.Contains(respBody, keyword) { 49 | result = true 50 | } else { 51 | result = false 52 | break 53 | } 54 | } 55 | } else { 56 | if strings.Contains(respBody, bodyFinger) { 57 | result = true 58 | } else { 59 | result = false 60 | } 61 | } 62 | } 63 | return result 64 | } 65 | 66 | func identifyService(pattern string, reply []byte) bool { 67 | //for _, rep := range reply { 68 | check, _ := regexp.Match(pattern, reply) 69 | if check { 70 | return true 71 | } 72 | //} 73 | return false 74 | } 75 | -------------------------------------------------------------------------------- /common/portscan/init.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "Mscan/common/brute" 5 | "Mscan/common/util" 6 | "fmt" 7 | "github.com/kpango/glg" 8 | "github.com/malfunkt/iprange" 9 | "strconv" 10 | "strings" 11 | "sync" 12 | ) 13 | 14 | //gen ip slice 15 | func (s *Scan) getIpList() error { 16 | list, err := iprange.ParseList(s.addrs) 17 | if err != nil { 18 | return err 19 | } 20 | rangeList := list.Expand() 21 | for _, ip := range rangeList { 22 | s.ipList = append(s.ipList, ip.String()) 23 | } 24 | return nil 25 | } 26 | 27 | //gen port slice 28 | func (s *Scan) getPortList() error { 29 | //处理端口为空的情况,为空默认扫全端口 30 | if s.ports == "" { 31 | //s.portList = util.MakeRangeSlice(1, 65535) 32 | s.portList = util.DefaultPorts 33 | return nil 34 | } 35 | commaSplit := strings.Split(s.ports, ",") 36 | for _, str := range commaSplit { 37 | str = strings.TrimSpace(str) 38 | if strings.Contains(str, "-") { 39 | parts := strings.Split(str, "-") 40 | if len(parts) != 2 { 41 | return fmt.Errorf("格式错误: %s", str) 42 | } 43 | port1, err := strconv.Atoi(parts[0]) 44 | if err != nil { 45 | return fmt.Errorf("端口号错误: %s", parts[0]) 46 | } 47 | port2, err := strconv.Atoi(parts[1]) 48 | if err != nil { 49 | return fmt.Errorf("端口号错误: %s", parts[1]) 50 | } 51 | if port1 > port2 { 52 | return fmt.Errorf("端口范围错误: %d-%d", port1, port2) 53 | } 54 | for i := port1; i <= port2; i++ { 55 | s.portList = append(s.portList, i) 56 | } 57 | } else { 58 | if port, err := strconv.Atoi(str); err != nil { 59 | return fmt.Errorf("端口号错误: %s", str) 60 | } else { 61 | s.portList = append(s.portList, port) 62 | } 63 | } 64 | } 65 | return nil 66 | } 67 | 68 | //gen all 69 | func (s *Scan) genScanTarget() { 70 | if err := s.getIpList(); err != nil { 71 | glg.Error(err) 72 | } 73 | if err := s.getPortList(); err != nil { 74 | glg.Error(err) 75 | } 76 | } 77 | 78 | //get finger slice 79 | func (s *Scan) getFinger() { 80 | for _, finger := range util.Fingers { 81 | if finger.Path == "/" && finger.Method == "GET" { 82 | s.defaultFinger = append(s.defaultFinger, finger) 83 | } else { 84 | s.customFinger = append(s.customFinger, finger) 85 | } 86 | } 87 | } 88 | 89 | //init brute chan 90 | func (s *Scan) initBruteChan() sync.Map { 91 | brt := brute.NewBrute(s.bruteModule, s.thread, s.bruteChan) 92 | //glg.Info("[+]准备弱口令扫描") 93 | brt.BrutePool() 94 | glg.Success("[+]弱口令扫描已完成") 95 | return brt.BruteResult 96 | } 97 | 98 | //send brute target 99 | func (s *Scan) sendBruteTarget(service, target string) { 100 | //通用情况 101 | if s.bruteModule == service { 102 | s.bruteChan <- util.Target{Service: service, Target: target} 103 | } 104 | //mssql 105 | if s.bruteModule == "mssql" && service == "ms-sql-s" { 106 | s.bruteChan <- util.Target{Service: service, Target: target} 107 | } 108 | //smb 109 | if s.bruteModule == "smb" && service == "microsoft-ds" { 110 | s.bruteChan <- util.Target{Service: service, Target: target} 111 | } 112 | //mongo 113 | if s.bruteModule == "mongo" && service == "mongodb" { 114 | s.bruteChan <- util.Target{Service: service, Target: target} 115 | } 116 | //postgre 117 | if s.bruteModule == "postgre" && service == "postgresql" { 118 | s.bruteChan <- util.Target{Service: service, Target: target} 119 | } 120 | //all 121 | if s.bruteModule == "all" && service != "rdp" { 122 | s.bruteChan <- util.Target{Service: service, Target: target} 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /common/portscan/scan.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "Mscan/common/util" 5 | "github.com/kpango/glg" 6 | "net" 7 | "strconv" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | type Scan struct { 13 | addrs string 14 | ports string 15 | ipList []string 16 | portList []int 17 | hostChan chan string 18 | targetChan chan string 19 | thread int 20 | wg *sync.WaitGroup 21 | lock *sync.Mutex 22 | workerChan chan struct{} 23 | respData chan *util.HttpRes 24 | defaultFinger []util.WebFinger 25 | customFinger []util.WebFinger 26 | WebResult util.WebResult 27 | Result map[string]*util.DetailResult 28 | sendChan chan *ServiceRep 29 | openChan chan *ServiceRep 30 | repChan chan *ServiceRep 31 | bruteModule string 32 | bruteChan chan util.Target 33 | BruteResult sync.Map 34 | } 35 | 36 | func NewScan(add, port string, threat int, group *sync.WaitGroup, mutex *sync.Mutex, brute string) *Scan { 37 | return &Scan{ 38 | addrs: add, 39 | ports: port, 40 | thread: threat, 41 | wg: group, 42 | lock: mutex, 43 | bruteModule: brute, 44 | } 45 | } 46 | 47 | func (s *Scan) scanWorker() { 48 | var wg = &sync.WaitGroup{} 49 | for ip := range s.hostChan { 50 | ip := ip 51 | s.lock.Lock() 52 | s.Result[ip] = &util.DetailResult{} 53 | s.Result[ip].WebInfo = make(map[string]*util.WebResult) 54 | s.lock.Unlock() 55 | for _, port := range s.portList { 56 | wg.Add(1) 57 | s.workerChan <- struct{}{} 58 | port := port 59 | go func() { 60 | target := net.JoinHostPort(ip, strconv.Itoa(port)) 61 | var service = &ServiceRep{} 62 | service.Ip = ip 63 | service.Port = port 64 | service.Target = target 65 | s.sendChan <- service 66 | <-s.workerChan 67 | wg.Done() 68 | }() 69 | } 70 | } 71 | wg.Wait() 72 | close(s.workerChan) 73 | close(s.sendChan) 74 | } 75 | 76 | func (s *Scan) ScanPool() map[string]*util.DetailResult { 77 | //init 78 | s.Result = make(map[string]*util.DetailResult) 79 | s.hostChan = make(chan string, 10) 80 | s.repChan = make(chan *ServiceRep, s.thread) 81 | s.sendChan = make(chan *ServiceRep, s.thread) 82 | s.openChan = make(chan *ServiceRep, s.thread) 83 | s.targetChan = make(chan string, s.thread) 84 | s.respData = make(chan *util.HttpRes, s.thread) 85 | s.workerChan = make(chan struct{}, s.thread) 86 | s.genScanTarget() 87 | s.getFinger() 88 | //brute module 89 | if s.bruteModule != "nb" { 90 | s.bruteChan = make(chan util.Target, s.thread) 91 | } 92 | //start work 93 | s.wg.Add(8) 94 | go func() { 95 | if s.bruteModule != "nb" { 96 | //init brute channel 97 | s.BruteResult = s.initBruteChan() 98 | } 99 | s.wg.Done() 100 | }() 101 | go func() { 102 | s.hostScan() 103 | s.wg.Done() 104 | }() 105 | go func() { 106 | s.scanWorker() 107 | s.wg.Done() 108 | }() 109 | go func() { 110 | s.checkWorker() 111 | s.wg.Done() 112 | }() 113 | go func() { 114 | s.sendWorker() 115 | s.wg.Done() 116 | }() 117 | go func() { 118 | s.serviceWorker() 119 | s.wg.Done() 120 | }() 121 | go func() { 122 | s.identifyFinger() 123 | s.wg.Done() 124 | }() 125 | go func() { 126 | s.checkFinger() 127 | s.wg.Done() 128 | }() 129 | s.wg.Wait() 130 | for k, v := range s.Result { 131 | glg.Infof("[+]ip: %s, ports: %v, service: %v, ", k, &v.Ports, &v.Service) 132 | for url, value := range v.WebInfo { 133 | glg.Infof("[+]url: %v, webTitle: %v, webStatus: %v, webFinger: %v", url, value.Title, value.StatusCode, util.RemoveRepByLoop(value.Finger)) 134 | } 135 | } 136 | return s.Result 137 | } 138 | 139 | func tcpConn(target string) (net.Conn, error) { 140 | conn, err := net.DialTimeout("tcp", target, time.Duration(2)*time.Second) 141 | if err != nil { 142 | return nil, err 143 | } 144 | err = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second)) 145 | if err != nil { 146 | if conn != nil { 147 | _ = conn.Close() 148 | } 149 | return nil, err 150 | } 151 | return conn, nil 152 | } 153 | -------------------------------------------------------------------------------- /common/portscan/send.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "Mscan/common/util" 5 | "bytes" 6 | "github.com/kpango/glg" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | func defaultSend(target string) ([]byte, error) { 12 | conn, err := tcpConn(target) 13 | if err != nil { 14 | return nil, err 15 | } 16 | _ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second)) 17 | rep := make([]byte, 256) 18 | _, err = conn.Read(rep) 19 | var buf [256]byte 20 | if err == nil && bytes.Equal(rep[:], buf[:]) == false { 21 | if conn != nil { 22 | _ = conn.Close() 23 | } 24 | return rep, nil 25 | } 26 | 27 | conn, err = tcpConn(target) 28 | if err != nil { 29 | return nil, err 30 | } 31 | _ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second)) 32 | msg := "GET / HTTP/1.1\r\n\r\n" 33 | _, err = conn.Write([]byte(msg)) 34 | if err != nil { 35 | return nil, err 36 | } 37 | rep = make([]byte, 256) 38 | _, _ = conn.Read(rep) 39 | if conn != nil { 40 | _ = conn.Close() 41 | } 42 | return rep, nil 43 | } 44 | 45 | func commonSend(target string) ([]byte, error) { 46 | conn, err := tcpConn(target) 47 | if err != nil { 48 | return nil, err 49 | } 50 | msg := "\r\n\r\n" 51 | _, err = conn.Write([]byte(msg)) 52 | if err != nil { 53 | return nil, err 54 | } 55 | _ = conn.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) 56 | rep := make([]byte, 256) 57 | _, _ = conn.Read(rep) 58 | if conn != nil { 59 | _ = conn.Close() 60 | } 61 | if rep != nil { 62 | return rep, nil 63 | } 64 | return nil, nil 65 | } 66 | 67 | func redisSend(target string) ([]byte, error) { 68 | conn, err := tcpConn(target) 69 | if err != nil { 70 | return nil, err 71 | } 72 | msg := "*1\r\n$4\r\ninfo\r\n" 73 | _, err = conn.Write([]byte(msg)) 74 | if err != nil { 75 | return nil, err 76 | } 77 | _ = conn.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) 78 | rep := make([]byte, 256) 79 | _, _ = conn.Read(rep) 80 | if conn != nil { 81 | _ = conn.Close() 82 | } 83 | if rep != nil { 84 | return rep, nil 85 | } 86 | return nil, nil 87 | } 88 | 89 | func mssqlSend(target string) ([]byte, error) { 90 | conn, err := tcpConn(target) 91 | if err != nil { 92 | return nil, err 93 | } 94 | msg := "\x12\x01\x00\x34\x00\x00\x00\x00\x00\x00\x15\x00\x06\x01\x00\x1b\x00\x01\x02\x00\x1c\x00\x0c\x03\x00\x28\x00\x04\xff\x08\x00\x01\x55\x00\x00\x00\x4d\x53\x53\x51\x4c\x53\x65\x72\x76\x65\x72\x00\x48\x0f\x00\x00" 95 | _, err = conn.Write([]byte(msg)) 96 | if err != nil { 97 | return nil, err 98 | } 99 | _ = conn.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) 100 | rep := make([]byte, 256) 101 | _, _ = conn.Read(rep) 102 | if conn != nil { 103 | _ = conn.Close() 104 | } 105 | if rep != nil { 106 | return rep, nil 107 | } 108 | return nil, nil 109 | } 110 | 111 | func smbProgNegSend(target string) ([]byte, error) { 112 | conn, err := tcpConn(target) 113 | if err != nil { 114 | return nil, err 115 | } 116 | msg := "\x00\x00\x00\xa4\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x08\x01\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x06\x00\x00\x01\x00\x00\x81\x00\x02PC NETWORK PROGRAM 1.0\x00\x02MICROSOFT NETWORKS 1.03\x00\x02MICROSOFT NETWORKS 3.0\x00\x02LANMAN1.0\x00\x02LM1.2X002\x00\x02Samba\x00\x02NT LANMAN 1.0\x00\x02NT LM 0.12\x00" 117 | _, err = conn.Write([]byte(msg)) 118 | if err != nil { 119 | return nil, err 120 | } 121 | _ = conn.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) 122 | rep := make([]byte, 256) 123 | _, _ = conn.Read(rep) 124 | if conn != nil { 125 | _ = conn.Close() 126 | } 127 | if rep != nil { 128 | return rep, nil 129 | } 130 | return nil, nil 131 | } 132 | 133 | func mongoSend(target string) ([]byte, error) { 134 | conn, err := tcpConn(target) 135 | if err != nil { 136 | return nil, err 137 | } 138 | msg := "\x41\x00\x00\x00\x3a\x30\x00\x00\xff\xff\xff\xff\xd4\x07\x00\x00\x00\x00\x00\x00test.$cmd\x00\x00\x00\x00\x00\xff\xff\xff\xff\x1b\x00\x00\x00\x01serverStatus\x00\x00\x00\x00\x00\x00\x00\xf0\x3f\x00" 139 | _, err = conn.Write([]byte(msg)) 140 | if err != nil { 141 | return nil, err 142 | } 143 | _ = conn.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) 144 | rep := make([]byte, 256) 145 | _, _ = conn.Read(rep) 146 | if conn != nil { 147 | _ = conn.Close() 148 | } 149 | if rep != nil { 150 | return rep, nil 151 | } 152 | return nil, nil 153 | } 154 | 155 | func rdpSend(target string) ([]byte, error) { 156 | conn, err := tcpConn(target) 157 | if err != nil { 158 | return nil, err 159 | } 160 | msg := "\x03\x00\x00\x2b\x26\xe0\x00\x00\x00\x00\x00\x43\x6f\x6f\x6b\x69\x65\x3a\x20\x6d\x73\x74\x73\x68\x61\x73\x68\x3d\x75\x73\x65\x72\x30\x0d\x0a\x01\x00\x08\x00\x00\x00\x00\x00" 161 | _, err = conn.Write([]byte(msg)) 162 | if err != nil { 163 | return nil, err 164 | } 165 | _ = conn.SetDeadline(time.Now().Add(time.Duration(3) * time.Second)) 166 | rep := make([]byte, 256) 167 | _, _ = conn.Read(rep) 168 | if conn != nil { 169 | _ = conn.Close() 170 | } 171 | if rep != nil { 172 | return rep, nil 173 | } 174 | return nil, nil 175 | } 176 | 177 | func (s *Scan) checkWorker() { 178 | var wg = &sync.WaitGroup{} 179 | workChan := make(chan struct{}, s.thread/4) 180 | for service := range s.sendChan { 181 | service := service 182 | wg.Add(1) 183 | workChan <- struct{}{} 184 | go func() { 185 | rep, err := defaultSend(service.Target) 186 | if err != nil { 187 | wg.Done() 188 | <-workChan 189 | return 190 | } 191 | if rep != nil { 192 | s.lock.Lock() 193 | glg.Infof("[+]发现端口:%s/open", service.Target) 194 | s.Result[service.Ip].Ports = append(s.Result[service.Ip].Ports, service.Port) 195 | //service.Rep = append(service.Rep, rep) 196 | service.Tag = "default" 197 | service.Rep = []byte(util.Convert(string(rep))) 198 | s.lock.Unlock() 199 | //s.repChan <- service 200 | s.openChan <- service 201 | } 202 | wg.Done() 203 | <-workChan 204 | }() 205 | } 206 | wg.Wait() 207 | glg.Success("[+]端口扫描已完成!") 208 | close(s.openChan) 209 | close(workChan) 210 | } 211 | 212 | func (s *Scan) sendWorker() { 213 | var wg = &sync.WaitGroup{} 214 | workChan := make(chan struct{}, s.thread/6) 215 | for openTarget := range s.openChan { 216 | openTarget := openTarget 217 | wg.Add(6) 218 | workChan <- struct{}{} 219 | go func() { 220 | rep, err := commonSend(openTarget.Target) 221 | if err != nil { 222 | wg.Done() 223 | <-workChan 224 | return 225 | } 226 | if rep != nil { 227 | var newTarget = &ServiceRep{} 228 | newTarget.Ip = openTarget.Ip 229 | newTarget.Port = openTarget.Port 230 | newTarget.Target = openTarget.Target 231 | newTarget.Tag = "common" 232 | newTarget.Rep = []byte(util.Convert(string(rep))) 233 | s.repChan <- openTarget 234 | } 235 | wg.Done() 236 | <-workChan 237 | }() 238 | workChan <- struct{}{} 239 | go func() { 240 | rep, err := redisSend(openTarget.Target) 241 | if err != nil { 242 | wg.Done() 243 | <-workChan 244 | return 245 | } 246 | if rep != nil { 247 | var newTarget = &ServiceRep{} 248 | newTarget.Ip = openTarget.Ip 249 | newTarget.Port = openTarget.Port 250 | newTarget.Target = openTarget.Target 251 | newTarget.Tag = "redis" 252 | newTarget.Rep = []byte(util.Convert(string(rep))) 253 | s.repChan <- newTarget 254 | } 255 | wg.Done() 256 | <-workChan 257 | }() 258 | workChan <- struct{}{} 259 | go func() { 260 | rep, err := mssqlSend(openTarget.Target) 261 | if err != nil { 262 | wg.Done() 263 | <-workChan 264 | return 265 | } 266 | if rep != nil { 267 | var newTarget = &ServiceRep{} 268 | newTarget.Ip = openTarget.Ip 269 | newTarget.Port = openTarget.Port 270 | newTarget.Target = openTarget.Target 271 | newTarget.Tag = "mssql" 272 | newTarget.Rep = []byte(util.Convert(string(rep))) 273 | s.repChan <- newTarget 274 | } 275 | wg.Done() 276 | <-workChan 277 | }() 278 | workChan <- struct{}{} 279 | go func() { 280 | rep, err := smbProgNegSend(openTarget.Target) 281 | if err != nil { 282 | wg.Done() 283 | <-workChan 284 | return 285 | } 286 | if rep != nil { 287 | var newTarget = &ServiceRep{} 288 | newTarget.Ip = openTarget.Ip 289 | newTarget.Port = openTarget.Port 290 | newTarget.Target = openTarget.Target 291 | newTarget.Tag = "smb" 292 | newTarget.Rep = []byte(util.Convert(string(rep))) 293 | s.repChan <- newTarget 294 | } 295 | wg.Done() 296 | <-workChan 297 | }() 298 | workChan <- struct{}{} 299 | go func() { 300 | rep, err := mongoSend(openTarget.Target) 301 | if err != nil { 302 | wg.Done() 303 | <-workChan 304 | return 305 | } 306 | if rep != nil { 307 | var newTarget = &ServiceRep{} 308 | newTarget.Ip = openTarget.Ip 309 | newTarget.Port = openTarget.Port 310 | newTarget.Target = openTarget.Target 311 | newTarget.Tag = "mongo" 312 | newTarget.Rep = []byte(util.Convert(string(rep))) 313 | s.repChan <- newTarget 314 | } 315 | wg.Done() 316 | <-workChan 317 | }() 318 | workChan <- struct{}{} 319 | go func() { 320 | rep, err := rdpSend(openTarget.Target) 321 | if err != nil { 322 | wg.Done() 323 | <-workChan 324 | return 325 | } 326 | if rep != nil { 327 | var newTarget = &ServiceRep{} 328 | newTarget.Ip = openTarget.Ip 329 | newTarget.Port = openTarget.Port 330 | newTarget.Target = openTarget.Target 331 | newTarget.Tag = "rdp" 332 | newTarget.Rep = []byte(util.Convert(string(rep))) 333 | s.repChan <- newTarget 334 | } 335 | wg.Done() 336 | <-workChan 337 | }() 338 | } 339 | wg.Wait() 340 | close(s.repChan) 341 | close(workChan) 342 | } 343 | -------------------------------------------------------------------------------- /common/portscan/service.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "Mscan/common/util" 5 | "github.com/kpango/glg" 6 | "strconv" 7 | "sync" 8 | ) 9 | 10 | type ServiceRep struct { 11 | Ip string 12 | Port int 13 | Target string 14 | Tag string 15 | Rep []byte 16 | } 17 | 18 | func (s *Scan) serviceWorker() { 19 | var wg = &sync.WaitGroup{} 20 | var cache sync.Map 21 | for repStruct := range s.repChan { 22 | repStruct := repStruct 23 | wg.Add(2) 24 | //判断是否http 25 | go func() { 26 | if identifyHttp(repStruct.Rep) { 27 | //去重 28 | web, _ := cache.Load(repStruct.Target) 29 | if web == "web" { 30 | wg.Done() 31 | return 32 | } else { 33 | cache.Store(repStruct.Target, "web") 34 | } 35 | glg.Infof("[+]发现web服务:%s:%v", repStruct.Ip, repStruct.Port) 36 | s.lock.Lock() 37 | s.Result[repStruct.Ip].Service = append(s.Result[repStruct.Ip].Service, strconv.Itoa(repStruct.Port)+":web") 38 | s.lock.Unlock() 39 | s.targetChan <- repStruct.Target 40 | } 41 | wg.Done() 42 | }() 43 | 44 | //主机服务识别 45 | go func() { 46 | for _, service := range util.Service { 47 | if identifyService(service.Pattern, repStruct.Rep) { 48 | //去重 49 | srv, _ := cache.Load(repStruct.Target) 50 | if srv == service.Service { 51 | wg.Done() 52 | return 53 | } else { 54 | cache.Store(repStruct.Target, service.Service) 55 | } 56 | if s.bruteModule != "nb" { 57 | s.sendBruteTarget(service.Service, repStruct.Target) 58 | } 59 | glg.Infof("[+]发现%s服务: %s:%v", service.Service, repStruct.Ip, repStruct.Port) 60 | s.lock.Lock() 61 | s.Result[repStruct.Ip].Service = append(s.Result[repStruct.Ip].Service, strconv.Itoa(repStruct.Port)+":"+service.Service) 62 | s.lock.Unlock() 63 | } 64 | } 65 | s.lock.Lock() 66 | s.Result[repStruct.Ip].Service = util.RemoveRepByLoop(s.Result[repStruct.Ip].Service) 67 | s.lock.Unlock() 68 | wg.Done() 69 | }() 70 | 71 | } 72 | glg.Success("[+]指纹匹配已完成") 73 | wg.Wait() 74 | close(s.targetChan) 75 | if s.bruteModule != "nb" { 76 | close(s.bruteChan) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /common/util/config.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | //var UserList = []string{"root", "administrator"} 4 | //var PassList = []string{"root", "!@", "wubao", "password", "123456", "admin", "12345", "1234", "p@ssw0rd", "123", "1", "jiamima", "test", "root123", "!", "!q@w", "!qaz@wsx", "idc!@", "admin!@", "alpine", "qwerty", "12345678", "111111", "123456789", "1q2w3e4r", "123123", "default", "1234567", "qwe123", "1qaz2wsx", "1234567890", "abcd1234", "000000", "user", "toor", "qwer1234", "1q2w3e", "asdf1234", "redhat", "1234qwer", "cisco", "12qwaszx", "test123", "1q2w3e4r5t", "admin123", "changeme", "1qazxsw2", "123qweasd", "q1w2e3r4", "letmein", "server", "root1234", "master", "abc123", "rootroot", "a", "system", "pass", "1qaz2wsx3edc", "p@$$w0rd", "112233", "welcome", "!QAZ2wsx", "linux", "123321", "manager", "1qazXSW@", "q1w2e3r4t5", "oracle", "asd123", "admin123456", "ubnt", "123qwe", "qazwsxedc", "administrator", "superuser", "zaq12wsx", "121212", "654321", "ubuntu", "0000", "zxcvbnm", "root@123", "1111", "vmware", "q1w2e3", "qwerty123", "cisco123", "11111111", "pa55w0rd", "asdfgh", "11111", "123abc", "asdf", "centos", "888888", "54321", "password123"} 5 | 6 | var FtpUser = []string{"ftp", "admin", "test"} 7 | var FtpPwd = []string{"ftp", "admin", "123456", "test"} 8 | 9 | var MssqlUser = []string{"sa"} 10 | var MssqlPwd = []string{"123456", "sa"} 11 | 12 | var MysqlUser = []string{"root"} 13 | var MysqlPwd = []string{"root", "123456", "password", "root!@#"} 14 | 15 | var PostgresUser = []string{"postgres"} 16 | var PostgresPwd = []string{"postgres"} 17 | 18 | var SmbUser = []string{"administrator"} 19 | var SmbPwd = []string{"password", "123456", "test", "admin", "administrator123", "Passw0rd", "123qwe", "test123", "admin123", "1q2w3e4r", "1qaz2wsx", "123456qwerty", "qazwsx", "root", "12345", "123", "qwerty"} 20 | 21 | var SshUser = []string{"root", "admin"} 22 | var SshPwd = []string{"root", "admin", "123456"} 23 | 24 | var DefaultPorts = []int{21, 22, 23, 25, 80, 81, 110, 111, 123, 135, 139, 389, 443, 445, 465, 500, 515, 548, 623, 636, 873, 902, 1080, 1099, 1433, 1521, 1883, 2049, 2181, 2375, 2379, 3128, 3306, 3389, 4730, 5222, 5432, 5555, 5601, 5672, 5900, 5938, 5984, 6000, 6379, 7001, 7077, 8080, 8081, 8443, 8545, 8686, 9000, 9001, 9042, 9092, 9100, 9200, 9418, 9999, 11211, 27017, 37777, 50000, 50070, 61616} 25 | 26 | type Target struct { 27 | Service string 28 | Target string 29 | } 30 | 31 | type Result struct { 32 | Addr *string 33 | User string 34 | Pass string 35 | } 36 | 37 | type WebResult struct { 38 | StatusCode string 39 | Title string 40 | Finger []string 41 | } 42 | 43 | type HttpRes struct { 44 | Target string 45 | Url string 46 | RespTitle string 47 | RespStatusCode string 48 | RespHeader string 49 | RespBody string 50 | } 51 | 52 | type DetailResult struct { 53 | Ports []int 54 | Service []string 55 | WebInfo map[string]*WebResult 56 | } 57 | -------------------------------------------------------------------------------- /common/util/output.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/kpango/glg" 6 | "os" 7 | ) 8 | 9 | type Csv struct { 10 | Ip string `csv:"ip"` 11 | Ports string `csv:"ports"` 12 | WebTitle string `csv:"web_title"` 13 | Finger string `csv:"finger"` 14 | } 15 | 16 | // Output 输出选项 17 | func Output(outputmod string, result map[string]*DetailResult) { 18 | switch outputmod { 19 | case "json": 20 | outputJson(result) 21 | } 22 | 23 | } 24 | 25 | func outputJson(result map[string]*DetailResult) { 26 | data, err := json.MarshalIndent(result, "", " ") 27 | if err != nil { 28 | glg.Error(err) 29 | } 30 | file, err := os.OpenFile("./result.json", os.O_RDWR|os.O_CREATE, 0755) 31 | if err != nil { 32 | glg.Error(err) 33 | } 34 | defer file.Close() 35 | _, err = file.Write(data) 36 | if err != nil { 37 | glg.Error(err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "bufio" 5 | "crypto/tls" 6 | "fmt" 7 | "github.com/kpango/glg" 8 | "math/rand" 9 | "net/http" 10 | "os" 11 | "strconv" 12 | "time" 13 | "unicode/utf8" 14 | ) 15 | 16 | // MakeRangeSlice 生成连续切片,给全端口号使用 17 | func MakeRangeSlice(min, max int) []int { 18 | s := make([]int, max-min+1) 19 | for i := range s { 20 | s[i] = min + i 21 | } 22 | return s 23 | } 24 | 25 | // ReadDicFile 读取字典文件 26 | func ReadDicFile(dir string) []string { 27 | var list []string 28 | file, err := os.Open(dir) 29 | if err != nil { 30 | glg.Error(err) 31 | } 32 | defer file.Close() 33 | 34 | buf := bufio.NewScanner(file) 35 | for { 36 | if !buf.Scan() { 37 | break 38 | } 39 | line := buf.Text() 40 | list = append(list, line) 41 | } 42 | return list 43 | } 44 | 45 | // GetProgress 获取当前完成扫描队列 46 | func GetProgress(now int64, total int64) { 47 | if now == total { 48 | glg.Logf("[+]当前已完成队列: %v/%v", now, total) 49 | } else { 50 | glg.Logf("[+]当前已完成队列: %v/%v", now, total) 51 | } 52 | } 53 | 54 | // TimeCost 计算扫描耗时 55 | func TimeCost() func() { 56 | start := time.Now() 57 | return func() { 58 | cost := time.Since(start) 59 | glg.Successf("[+]本次扫描耗时:%v", cost) 60 | } 61 | } 62 | 63 | // InitLogo 初始化logo 64 | func InitLogo() { 65 | var str = "███╗ ███╗███████╗ ██████╗ █████╗ ███╗ ██╗\n████╗ ████║██╔════╝██╔════╝██╔══██╗████╗ ██║\n██╔████╔██║███████╗██║ ███████║██╔██╗ ██║\n██║╚██╔╝██║╚════██║██║ ██╔══██║██║╚██╗██║\n██║ ╚═╝ ██║███████║╚██████╗██║ ██║██║ ╚████║\n╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═══╝\n\nauthor: M1ku Version:0.3.1\n" 66 | fmt.Println(str) 67 | } 68 | 69 | func Client() *http.Client { 70 | return &http.Client{ 71 | Timeout: 3 * time.Second, 72 | Transport: &http.Transport{ 73 | TLSClientConfig: &tls.Config{ 74 | InsecureSkipVerify: true, 75 | }, 76 | DisableKeepAlives: true, 77 | }, 78 | /*CheckRedirect: func(req *http.Request, via []*http.Request) error { 79 | return http.ErrUseLastResponse 80 | },*/ 81 | } 82 | } 83 | 84 | // RemoveRepByLoop 字符串切片去重 85 | func RemoveRepByLoop(slc []string) []string { 86 | result := []string{} // 存放结果 87 | for i := range slc { 88 | flag := true 89 | for j := range result { 90 | if slc[i] == result[j] { 91 | flag = false // 存在重复元素,标识为false 92 | break 93 | } 94 | } 95 | if flag { // 标识为false,不添加进结果 96 | result = append(result, slc[i]) 97 | } 98 | } 99 | return result 100 | } 101 | 102 | // GetSrcPort 创建随机源端口,范围(10000-60000) 103 | func GetSrcPort() int { 104 | rand.Seed(time.Now().UnixNano()) 105 | port := rand.Intn(50000) + 10000 106 | return port 107 | } 108 | 109 | func toStringSlice(a []int) []string { 110 | var s []string 111 | for _, v := range a { 112 | s = append(s, strconv.Itoa(v)) 113 | } 114 | return s 115 | } 116 | 117 | func Convert(src string) string { 118 | var dst string = "" 119 | for i, r := range src { 120 | var v string = "" 121 | if r == utf8.RuneError { 122 | v = string(src[i]) 123 | } else { 124 | v = string(r) 125 | } 126 | dst += string(v) 127 | } 128 | return dst 129 | } 130 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | email: 2 | address: # smtp server address(ip or host) 3 | port: 25 4 | username: # email username 5 | password: # email password 6 | sendto: # send to email address 7 | dingtalk: 8 | token: 9 | - # dingtalk bot token 10 | key: # key 默认为空 11 | secret: # dingtalk bot secret 12 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module Mscan 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/denisenkom/go-mssqldb v0.12.0 7 | github.com/go-sql-driver/mysql v1.6.0 8 | github.com/gomodule/redigo v1.8.8 9 | github.com/hirochachacha/go-smb2 v1.0.10 10 | github.com/jlaffaye/ftp v0.0.0-20211117213618-11820403398b 11 | github.com/kpango/glg v1.6.10 12 | github.com/lib/pq v1.10.4 13 | github.com/malfunkt/iprange v0.9.0 14 | go.mongodb.org/mongo-driver v1.8.3 15 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 16 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 17 | ) 18 | 19 | require ( 20 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect 21 | github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect 22 | github.com/geoffgarside/ber v1.1.0 // indirect 23 | github.com/go-stack/stack v1.8.0 // indirect 24 | github.com/goccy/go-json v0.9.4 // indirect 25 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect 26 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect 27 | github.com/golang/snappy v0.0.1 // indirect 28 | github.com/klauspost/compress v1.13.6 // indirect 29 | github.com/kpango/fastime v1.1.4 // indirect 30 | github.com/pkg/errors v0.9.1 // indirect 31 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 32 | github.com/xdg-go/scram v1.0.2 // indirect 33 | github.com/xdg-go/stringprep v1.0.2 // indirect 34 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect 35 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect 36 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect 37 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect 38 | golang.org/x/text v0.3.6 // indirect 39 | ) 40 | -------------------------------------------------------------------------------- /imgs/E3D2A0DF-9441-4099-9442-03374D62639E.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmM1ku/Mscan/2a5b80ddc8d63c75473bc0175325b97fa269de29/imgs/E3D2A0DF-9441-4099-9442-03374D62639E.png -------------------------------------------------------------------------------- /imgs/WechatIMG22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmM1ku/Mscan/2a5b80ddc8d63c75473bc0175325b97fa269de29/imgs/WechatIMG22.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "Mscan/common/ScanTask" 5 | "Mscan/common/util" 6 | "gopkg.in/alecthomas/kingpin.v2" 7 | _ "net/http/pprof" 8 | ) 9 | 10 | var ( 11 | ips = kingpin.Flag("ip", "IP Range").Required().Short('i').String() 12 | ports = kingpin.Flag("port", "Port Range").Short('p').String() 13 | thread = kingpin.Flag("thread", "Scan Threads").Default("50").Short('t').Int() 14 | module = kingpin.Flag("module", "Brute Module").Default("all").Short('m').String() 15 | brutethread = kingpin.Flag("brute", "Brute Threads").Default("10").Short('b').Int() 16 | userpath = kingpin.Flag("upath", "User Dic Path").Short('u').String() 17 | passpath = kingpin.Flag("ppath", "Pass Dic Path").Short('w').String() 18 | output = kingpin.Flag("output", "Output Result").Short('o').String() 19 | ) 20 | 21 | func main() { 22 | defer util.TimeCost()() 23 | /*go func() { 24 | _ = http.ListenAndServe("0.0.0.0:8081", nil) 25 | }()*/ 26 | util.InitLogo() 27 | kingpin.Parse() 28 | task := ScanTask.NewTask(*ips, *ports, *thread, *module, *brutethread, *userpath, *passpath, *output) 29 | task.Run() 30 | task.Wg.Wait() 31 | } 32 | --------------------------------------------------------------------------------