├── 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 | 
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 |
--------------------------------------------------------------------------------