├── pkg ├── blasting │ ├── utils.go │ ├── snmpcli.go │ ├── zookeeper.go │ ├── memcache.go │ ├── docker.go │ ├── export.go │ ├── rdpcli.go │ ├── ftpcli.go │ ├── mssqlcli.go │ ├── mysqlcli.go │ ├── oraclecli.go │ ├── smbcli.go │ ├── mongodbcli.go │ ├── postgresqlcli.go │ ├── sshcli.go │ ├── rediscli.go │ └── telnetcli.go ├── sitescan │ ├── README.md │ ├── export.go │ ├── httpx.go │ └── request.go ├── grdp │ ├── core │ │ ├── io_test.go │ │ ├── types.go │ │ ├── rle_test.go │ │ ├── util.go │ │ ├── socket.go │ │ └── io.go │ ├── README.md │ ├── protocol │ │ ├── nla │ │ │ ├── encode_test.go │ │ │ ├── encode.go │ │ │ ├── cssp.go │ │ │ └── ntlm_test.go │ │ ├── t125 │ │ │ ├── per │ │ │ │ └── per.go │ │ │ ├── ber │ │ │ │ └── ber.go │ │ │ ├── mcs.go │ │ │ └── gcc │ │ │ │ └── gcc.go │ │ ├── lic │ │ │ └── lic.go │ │ ├── tpkt │ │ │ └── tpkt.go │ │ ├── x224 │ │ │ └── x224.go │ │ ├── pdu │ │ │ ├── cliprdr.go │ │ │ └── pdu.go │ │ └── rfb │ │ │ └── rfb.go │ ├── grdp_test.go │ ├── glog │ │ └── log.go │ ├── grdp.go │ └── emission │ │ └── emitter.go ├── portscan │ ├── export.go │ ├── masscan.go │ └── nmap.go ├── useragent │ └── main.go ├── log │ └── main.go └── parseip │ └── main.go ├── .images └── image-20221215195216505.png ├── config └── main.go ├── README.md ├── .github └── workflows │ └── go.yml ├── go.mod ├── cmd └── Monkey │ └── main.go ├── internal └── runner │ └── main.go └── go.sum /pkg/blasting/utils.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | type message struct { 4 | user string 5 | pass string 6 | } 7 | -------------------------------------------------------------------------------- /.images/image-20221215195216505.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bufsnake/Monkey/HEAD/.images/image-20221215195216505.png -------------------------------------------------------------------------------- /pkg/sitescan/README.md: -------------------------------------------------------------------------------- 1 | # http/https 请求模块 2 | 3 | > 凡是经过,则会获取以下内容 4 | > 5 | > Server 版本信息 6 | > URL MW X-Powered-By CODE LENGTH TITLE 7 | -------------------------------------------------------------------------------- /pkg/sitescan/export.go: -------------------------------------------------------------------------------- 1 | package sitescan 2 | 3 | func NewHttpx(host string, timeout int) *httpx { 4 | return &httpx{url: host, timeout: timeout} 5 | } 6 | 7 | func NewRequest(url string, timeout int) *request { 8 | return &request{url: url, timeout: timeout} 9 | } 10 | -------------------------------------------------------------------------------- /config/main.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type Config struct { 4 | Target string // 单个目标 5 | Targets string // 多个目标 6 | Thread int // 扫描线程 7 | Blast bool // 是否进行爆破 8 | Timeout int // http超时设置 9 | NmapSV string // nmap详细程度,默认为2,数值越大,耗时越久 nmap -sV --version-intensity 0~9 10 | Port string // 指定端口 nmap -p 0-65535 11 | MasScanRate string // masscan 扫描速率 masscan --rate 1000 12 | } 13 | -------------------------------------------------------------------------------- /pkg/grdp/core/io_test.go: -------------------------------------------------------------------------------- 1 | package core_test 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "github.com/bufsnake/Monkey/pkg/grdp/core" 7 | "testing" 8 | ) 9 | 10 | func TestWriteUInt16LE(t *testing.T) { 11 | buff := &bytes.Buffer{} 12 | core.WriteUInt32LE(66538, buff) 13 | result := hex.EncodeToString(buff.Bytes()) 14 | expected := "ea030100" 15 | if result != expected { 16 | t.Error(result, "not equals to", expected) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pkg/portscan/export.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "github.com/bufsnake/Monkey/config" 5 | ) 6 | 7 | type Service struct { 8 | IP string 9 | Port string 10 | Protocol string 11 | Version string 12 | ServiceFP string // 终端不输出,输出到CSV中 13 | } 14 | 15 | type portscan interface { 16 | PortScan(ip string) error 17 | GetService() []Service 18 | } 19 | 20 | func NewPortScan(config config.Config) portscan { 21 | return &mas_scan{conf: config, port: config.Port, nmapsv: config.NmapSV, masscan_rate: config.MasScanRate} 22 | } 23 | -------------------------------------------------------------------------------- /pkg/grdp/core/types.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "github.com/bufsnake/Monkey/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/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/blasting/snmpcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "github.com/gosnmp/gosnmp" 5 | "strconv" 6 | "time" 7 | ) 8 | 9 | type snmp struct { 10 | ip string 11 | port string 12 | } 13 | 14 | func (s *snmp) Info() string { 15 | return "weak" 16 | } 17 | 18 | func (s *snmp) Connect() (string, error) { 19 | gosnmp.Default.Target = s.ip 20 | temp, err := strconv.Atoi(s.port) 21 | gosnmp.Default.Port = uint16(temp) 22 | gosnmp.Default.Community = "public" 23 | gosnmp.Default.Timeout = 10 * time.Second 24 | err = gosnmp.Default.Connect() 25 | if err != nil { 26 | return "", err 27 | } 28 | oids := []string{"1.3.6.1.2.1.1.4.0", "1.3.6.1.2.1.1.7.0"} 29 | _, err = gosnmp.Default.Get(oids) 30 | if err != nil { 31 | return "", err 32 | } 33 | return "snmp://public@" + s.ip + ":" + s.port, nil 34 | } 35 | -------------------------------------------------------------------------------- /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) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 简介 2 | 3 | > 基于nmap、masscan的端口扫描工具 4 | 5 | ## 使用 6 | 7 | ```bash 8 | $ sudo ./Monkey -h 9 | Linux: sudo sysctl -w net.ipv4.ping_group_range="0 2147483647" 10 | Local IP is [192.168.67.74 198.18.0.1] ,ulimit -n is 10240 11 | 内网扫描需要配置网关,网关IP为任意一台存活IP即可 12 | Usage of ./Monkey: 13 | -blast 14 | blast service 15 | -masscan-rate string 16 | masscan rate (default "1000") 17 | -nmap-sv string 18 | nmap version intensity,optional 0~9 (default "2") 19 | -port string 20 | specify scan ports (default "0-65535") 21 | -target string 22 | specify target ip 23 | -targets string 24 | specify target ip from file 25 | -thread int 26 | specify scan threads (default 6) 27 | -timeout int 28 | web request timeout (default 10) 29 | ``` 30 | 31 | ![image-20221215195216505](.images/image-20221215195216505.png) 32 | 33 | ## 代办 34 | 35 | - [x] 端口扫描 36 | - [x] 指纹识别 37 | - [x] 暴力破解 38 | - [x] 网站识别 39 | - [x] 优化IP解析 -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-18.04 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | - name: Install Golang 14 | uses: actions/setup-go@v2 15 | with: 16 | go-version: 1.19.4 17 | 18 | - name: Get Current Date 19 | id: date 20 | run: echo "::set-output name=date::$(date +'%Y%m%d%H%M')" 21 | 22 | - name: Build && Packet 23 | run: | 24 | go build -v -ldflags '-w -s' -gcflags '-N -l' -o Monkey cmd/Monkey/main.go 25 | tar -zcvf Monkey.tar.gz Monkey 26 | 27 | - name: Auto Release 28 | uses: softprops/action-gh-release@v1 29 | env: 30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 31 | with: 32 | tag_name: ${{ steps.date.outputs.date }} 33 | release_name: Release ${{ steps.date.outputs.date }} 34 | files: | 35 | *.tar.gz 36 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/nla/encode_test.go: -------------------------------------------------------------------------------- 1 | package nla_test 2 | 3 | import ( 4 | "encoding/hex" 5 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/nla" 6 | "testing" 7 | ) 8 | 9 | func TestNTOWFv2(t *testing.T) { 10 | res := hex.EncodeToString(nla.NTOWFv2("", "", "")) 11 | expected := "f4c1a15dd59d4da9bd595599220d971a" 12 | if res != expected { 13 | t.Error(res, "not equal to", expected) 14 | } 15 | 16 | res = hex.EncodeToString(nla.NTOWFv2("user", "pwd", "dom")) 17 | expected = "652feb8208b3a8a6264c9c5d5b820979" 18 | if res != expected { 19 | t.Error(res, "not equal to", expected) 20 | } 21 | } 22 | 23 | func TestRC4K(t *testing.T) { 24 | key, _ := hex.DecodeString("55638e834ce774c100637f197bc0683f") 25 | src, _ := hex.DecodeString("177d16086dd3f06fa8d594e3bad005b7") 26 | res := hex.EncodeToString(nla.RC4K(key, src)) 27 | expected := "f5ab375222707a492bd5a90705d96d1d" 28 | if res != expected { 29 | t.Error(res, "not equal to", expected) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pkg/blasting/zookeeper.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "bufio" 5 | "errors" 6 | "net" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type zookeeper struct { 12 | ip string 13 | port string 14 | } 15 | 16 | func (s *zookeeper) Info() string { 17 | return "unau" 18 | } 19 | 20 | func (z *zookeeper) Connect() (string, error) { 21 | conn, err := net.DialTimeout("tcp", z.ip+":"+z.port, 3*time.Second) 22 | if err != nil { 23 | return "", err 24 | } 25 | defer conn.Close() 26 | conn.SetWriteDeadline(time.Now().Add(3 * time.Second)) 27 | _, err = conn.Write([]byte("envi\r\n")) 28 | if err != nil { 29 | return "", err 30 | } 31 | conn.SetReadDeadline(time.Now().Add(3 * time.Second)) 32 | reader := bufio.NewReader(conn) 33 | line, _ := reader.ReadString(byte('\n')) 34 | if !strings.Contains(line, "Environment") { 35 | return "", errors.New("zookeeper unauth test finish,but no connect found") 36 | } 37 | return "zookeeper://" + z.ip + ":" + z.port, err 38 | } 39 | -------------------------------------------------------------------------------- /pkg/blasting/memcache.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "bufio" 5 | "errors" 6 | "net" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type memcached struct { 12 | ip string 13 | port string 14 | } 15 | 16 | // 方便判断是啥类型的漏洞 17 | func (s *memcached) Info() string { 18 | return "unau" 19 | } 20 | 21 | func (m *memcached) Connect() (string, error) { 22 | conn, err := net.DialTimeout("tcp", m.ip+":"+m.port, 3*time.Second) 23 | if err != nil { 24 | return "", err 25 | } 26 | defer conn.Close() 27 | conn.SetWriteDeadline(time.Now().Add(3 * time.Second)) 28 | _, err = conn.Write([]byte("stats\r\n")) 29 | if err != nil { 30 | return "", err 31 | } 32 | conn.SetReadDeadline(time.Now().Add(3 * time.Second)) 33 | reader := bufio.NewReader(conn) 34 | line, _ := reader.ReadString(byte('\n')) 35 | if !strings.Contains(line, "STAT") { 36 | return "", errors.New("memcached unauth test finish,but no connect found") 37 | } 38 | return "memcached://" + m.ip + ":" + m.port, nil 39 | } 40 | -------------------------------------------------------------------------------- /pkg/grdp/grdp_test.go: -------------------------------------------------------------------------------- 1 | package grdp 2 | 3 | import ( 4 | "fmt" 5 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 6 | "testing" 7 | ) 8 | 9 | func testrdp(target string) { 10 | domain := "" 11 | username := "administrator" 12 | password := "zaq1@WSX" 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.217.147:3389", 42 | } 43 | for _, target := range targetArr { 44 | fmt.Println(target) 45 | testrdp(target) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pkg/sitescan/httpx.go: -------------------------------------------------------------------------------- 1 | package sitescan 2 | 3 | import ( 4 | "strings" 5 | "sync" 6 | ) 7 | 8 | type httpx struct { 9 | url string 10 | timeout int 11 | URLS []*request 12 | lock sync.Mutex 13 | } 14 | 15 | func (h *httpx) Run() error { 16 | httpv := "http://" + h.url 17 | httpvs := "https://" + h.url 18 | urlsp := strings.Split(h.url, ":") 19 | if len(urlsp) == 2 { 20 | if urlsp[1] == "80" { 21 | httpv = "http://" + urlsp[0] 22 | } else if urlsp[1] == "443" { 23 | httpvs = "https://" + urlsp[0] 24 | } 25 | } 26 | http := NewRequest(httpv, h.timeout) 27 | https := NewRequest(httpvs, h.timeout) 28 | wghttpx := sync.WaitGroup{} 29 | wghttpx.Add(2) 30 | go func() { 31 | defer wghttpx.Done() 32 | err := http.Run() 33 | if err == nil { 34 | h.lock.Lock() 35 | h.URLS = append(h.URLS, http) 36 | h.lock.Unlock() 37 | } 38 | }() 39 | go func() { 40 | defer wghttpx.Done() 41 | err := https.Run() 42 | if err == nil { 43 | h.lock.Lock() 44 | h.URLS = append(h.URLS, https) 45 | h.lock.Unlock() 46 | } 47 | }() 48 | wghttpx.Wait() 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/nla/encode.go: -------------------------------------------------------------------------------- 1 | package nla 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/md5" 6 | "crypto/rc4" 7 | core "github.com/bufsnake/Monkey/pkg/grdp/core" 8 | "strings" 9 | 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/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 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/bufsnake/Monkey 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/Ullaakut/nmap v1.0.0 7 | github.com/bufsnake/go-masscan v0.0.0-20210111015631-180a4e32f7bf 8 | github.com/denisenkom/go-mssqldb v0.12.0 9 | github.com/garyburd/redigo v1.6.3 10 | github.com/gosnmp/gosnmp v1.34.0 11 | github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 12 | github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5 13 | github.com/jlaffaye/ftp v0.0.0-20220310202011-d2c44e311e78 14 | github.com/lib/pq v1.10.5 15 | github.com/logrusorgru/aurora v2.0.3+incompatible 16 | github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 17 | github.com/pkg/errors v0.9.1 18 | github.com/sijms/go-ora/v2 v2.4.16 19 | github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8 20 | github.com/ziutek/mymysql v1.5.4 21 | golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 22 | golang.org/x/text v0.3.7 23 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 24 | ) 25 | 26 | require ( 27 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect 28 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect 29 | github.com/hashicorp/errwrap v1.0.0 // indirect 30 | github.com/hashicorp/go-multierror v1.1.1 // indirect 31 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect 32 | ) 33 | -------------------------------------------------------------------------------- /pkg/portscan/masscan.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "errors" 5 | "github.com/bufsnake/Monkey/config" 6 | "github.com/bufsnake/go-masscan" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | type mas_scan struct { 12 | conf config.Config 13 | port string 14 | nmapsv string 15 | masscan_rate string 16 | masscan_port string 17 | Services []Service 18 | } 19 | 20 | func (f *mas_scan) PortScan(ip string) error { 21 | err := f.getport(ip) 22 | if err != nil { 23 | return err 24 | } 25 | err = f.getsevice(ip) 26 | if err != nil { 27 | return err 28 | } 29 | return nil 30 | } 31 | 32 | func (f *mas_scan) GetService() []Service { 33 | return f.Services 34 | } 35 | 36 | func (r *mas_scan) getport(ip string) error { 37 | m := masscan.New() 38 | m.SetPorts(r.port) 39 | m.SetRate(r.masscan_rate) 40 | m.SetArgs([]string{ip, "--wait", "1"}...) 41 | err := m.Run() 42 | if err != nil { 43 | return err 44 | } 45 | results, err := m.Parse() 46 | if err != nil { 47 | return err 48 | } 49 | count := 0 50 | for _, result := range results { 51 | for _, ports := range result.Ports { 52 | r.masscan_port += ports.Portid + "," 53 | count++ 54 | } 55 | } 56 | if count > 1000 { 57 | return errors.New("too manay ports, there are " + strconv.Itoa(count) + " ports in total.") 58 | } 59 | if r.masscan_port == "" { 60 | return errors.New("not found port") 61 | } 62 | r.masscan_port = strings.Trim(r.masscan_port, ",") 63 | return nil 64 | } 65 | -------------------------------------------------------------------------------- /pkg/blasting/docker.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "crypto/tls" 5 | "fmt" 6 | "github.com/pkg/errors" 7 | "io/ioutil" 8 | "log" 9 | "net/http" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | type docker struct { 15 | ip string 16 | port string 17 | } 18 | 19 | func (s *docker) Info() string { 20 | return "unau" 21 | } 22 | 23 | func (d *docker) Connect() (string, error) { 24 | protocol := "docker" 25 | req_url := fmt.Sprintf("%s://%s:%s/version", "http", d.ip, d.port) 26 | res, err := d.req(req_url) 27 | if err != nil { 28 | protocol = "dockers" 29 | log.Println(err) 30 | req_url = fmt.Sprintf("%s://%s:%s/version", "https", d.ip, d.port) 31 | res, err = d.req(req_url) 32 | if err != nil { 33 | return "", err 34 | } 35 | } 36 | defer res.Body.Close() 37 | all, err := ioutil.ReadAll(res.Body) 38 | if err != nil { 39 | return "", err 40 | } 41 | if strings.Contains(string(all), "Version") && strings.Contains(string(all), "Arch") && strings.Contains(string(all), "Os") { 42 | return protocol + "://" + d.ip + ":" + d.port, nil 43 | } 44 | return "", errors.New("docker unauth test finish,but no connect found") 45 | } 46 | 47 | func (d *docker) req(req_url string) (*http.Response, error) { 48 | cli := http.Client{ 49 | Timeout: 10 * time.Second, 50 | Transport: &http.Transport{ 51 | TLSClientConfig: &tls.Config{ 52 | InsecureSkipVerify: true, 53 | }, 54 | }, 55 | } 56 | req, err := http.NewRequest("GET", req_url, nil) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return cli.Do(req) 61 | } 62 | -------------------------------------------------------------------------------- /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 | "errors" 10 | "net" 11 | 12 | "github.com/icodeface/tls" 13 | ) 14 | 15 | type SocketLayer struct { 16 | conn net.Conn 17 | tlsConn *tls.Conn 18 | } 19 | 20 | func NewSocketLayer(conn net.Conn) *SocketLayer { 21 | l := &SocketLayer{ 22 | conn: conn, 23 | tlsConn: nil, 24 | } 25 | return l 26 | } 27 | 28 | func (s *SocketLayer) Read(b []byte) (n int, err error) { 29 | if s.tlsConn != nil { 30 | return s.tlsConn.Read(b) 31 | } 32 | return s.conn.Read(b) 33 | } 34 | 35 | func (s *SocketLayer) Write(b []byte) (n int, err error) { 36 | if s.tlsConn != nil { 37 | return s.tlsConn.Write(b) 38 | } 39 | return s.conn.Write(b) 40 | } 41 | 42 | func (s *SocketLayer) Close() error { 43 | if s.tlsConn != nil { 44 | err := s.tlsConn.Close() 45 | if err != nil { 46 | return err 47 | } 48 | } 49 | return s.conn.Close() 50 | } 51 | 52 | func (s *SocketLayer) StartTLS() error { 53 | config := &tls.Config{ 54 | InsecureSkipVerify: true, 55 | MinVersion: tls.VersionTLS10, 56 | MaxVersion: tls.VersionTLS13, 57 | PreferServerCipherSuites: true, 58 | } 59 | s.tlsConn = tls.Client(s.conn, config) 60 | return s.tlsConn.Handshake() 61 | } 62 | 63 | type PublicKey struct { 64 | N *big.Int `asn1:"explicit,tag:0"` // modulus 65 | E int `asn1:"explicit,tag:1"` // public exponent 66 | } 67 | 68 | func (s *SocketLayer) TlsPubKey() ([]byte, error) { 69 | if s.tlsConn == nil { 70 | return nil, errors.New("TLS conn does not exist") 71 | } 72 | pub := s.tlsConn.ConnectionState().PeerCertificates[0].PublicKey.(*rsa.PublicKey) 73 | return asn1ber.Marshal(*pub) 74 | } 75 | -------------------------------------------------------------------------------- /pkg/blasting/export.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | type Blast interface { 10 | Connect() (string, error) 11 | Info() string 12 | } 13 | 14 | func NewBlast(service, ip, port string) (Blast, error) { 15 | atoi, err := strconv.Atoi(port) 16 | if err != nil { 17 | return nil, err 18 | } 19 | if atoi < 0 || atoi > 65535 { 20 | return nil, err 21 | } 22 | switch strings.ToUpper(service) { 23 | case "SSH", "SSL/SSH": 24 | return &clissh{ip: ip, port: port}, nil 25 | case "FTP", "SSL/FTP": 26 | return &cliftp{ip: ip, port: port}, nil 27 | case "MYSQL", "NAGIOS-NSCA", "SSL/MYSQL", "SSL/NAGIOS-NSCA": 28 | return &climysql{ip: ip, port: port}, nil 29 | case "MS-SQL-S", "SSL/MS-SQL-S": 30 | return &mssql{ip: ip, port: port}, nil 31 | case "REDIS", "SSL/REDIS": 32 | return &redis_cli{ip: ip, port: port}, nil 33 | case "MONGOD", "SSL/MONGOD", "MONGODB", "SSL/MONGODB": 34 | return &mongodb{ip: ip, port: port}, nil 35 | case "POSTGRESQL", "SSL/POSTGRESQL": 36 | return &postgresql{ip: ip, port: port}, nil 37 | case "MICROSOFT-DS", "SSL/MICROSOFT-DS": 38 | return &clismb{ip: ip, port: port}, nil 39 | case "SNMP", "SSL/SNMP": 40 | return &snmp{ip: ip, port: port}, nil 41 | case "DOCKER", "SSL/DOCKER": 42 | return &docker{ip: ip, port: port}, nil 43 | case "ZOOKEEPER", "SSL/ZOOKEEPER": 44 | return &zookeeper{ip: ip, port: port}, nil 45 | case "MEMCACHE", "SSL/MEMCACHE": 46 | return &memcached{ip: ip, port: port}, nil 47 | case "MS-WBT-SERVER", "SSL/MS-WBT-SERVER": 48 | return &rdpcli{ip: ip, port: port}, nil 49 | case "TELNET", "SSL/TELNET": 50 | return &telnetcli{ip: ip, port: port}, nil 51 | case "ORACLE", "SSL/ORACLE": 52 | return &oraclecli{ip: ip, port: port}, nil 53 | default: 54 | return nil, errors.New("found no protocol") 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pkg/portscan/nmap.go: -------------------------------------------------------------------------------- 1 | package portscan 2 | 3 | import ( 4 | "github.com/Ullaakut/nmap" 5 | "github.com/bufsnake/Monkey/pkg/useragent" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | func (r *mas_scan) getsevice(ip string) error { 12 | retry := true 13 | again: 14 | scanner, err := nmap.NewScanner( 15 | nmap.WithCustomArguments("--disable-arp-ping"), 16 | nmap.WithCustomArguments("-sV"), 17 | nmap.WithCustomArguments("--version-intensity"), 18 | nmap.WithCustomArguments(r.nmapsv), // 0-9 19 | nmap.WithCustomArguments("-Pn"), 20 | nmap.WithCustomArguments("--script-args"), 21 | nmap.WithCustomArguments("http.useragent=\""+useragent.RandomUserAgent()+"\""), 22 | nmap.WithCustomArguments("-p"), 23 | nmap.WithCustomArguments(r.masscan_port), 24 | nmap.WithCustomArguments("-n"), 25 | nmap.WithCustomArguments("-r"), 26 | nmap.WithCustomArguments(ip), 27 | ) 28 | if err != nil { 29 | return err 30 | } 31 | run, _, err := scanner.Run() 32 | if err != nil { 33 | if retry && strings.Contains(err.Error(), "unable to parse nmap output") { 34 | retry = false 35 | time.Sleep(2 * time.Second) 36 | goto again 37 | } 38 | return err 39 | } 40 | for _, hosts := range run.Hosts { 41 | for _, ports := range hosts.Ports { 42 | if len(ports.Service.ServiceFP) != 0 && ports.Service.Name != "unknown" { 43 | ports.Service.Name = ports.Service.Name + "?" 44 | } 45 | if len(ports.Service.Tunnel) != 0 { 46 | ports.Service.Name = ports.Service.Tunnel + "/" + ports.Service.Name 47 | } 48 | if strings.Contains(ports.Service.ServiceFP, "HTTP") { 49 | ports.Service.Name = "http" 50 | } 51 | r.Services = append(r.Services, Service{IP: ip, Port: strconv.Itoa(int(ports.ID)), Protocol: ports.Service.Name, Version: strings.Trim(ports.Service.Product+" "+ports.Service.Version, " "), ServiceFP: ports.Service.ServiceFP}) 52 | } 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/useragent/main.go: -------------------------------------------------------------------------------- 1 | package useragent 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | ) 7 | 8 | func RandomUserAgent() string { 9 | return []func() string{genFirefoxUA, genChromeUA, genOperaUA}[rand.Intn(3)]() 10 | } 11 | 12 | var ffVersions = []float32{ 13 | 35.0, 14 | 40.0, 15 | 41.0, 16 | 44.0, 17 | 45.0, 18 | 48.0, 19 | 48.0, 20 | 49.0, 21 | 50.0, 22 | 52.0, 23 | 52.0, 24 | 53.0, 25 | 54.0, 26 | 56.0, 27 | 57.0, 28 | 57.0, 29 | 58.0, 30 | 58.0, 31 | 59.0, 32 | 6.0, 33 | 60.0, 34 | 61.0, 35 | 63.0, 36 | } 37 | 38 | var chromeVersions = []string{ 39 | "37.0.2062.124", 40 | "40.0.2214.93", 41 | "41.0.2228.0", 42 | "49.0.2623.112", 43 | "55.0.2883.87", 44 | "56.0.2924.87", 45 | "57.0.2987.133", 46 | "61.0.3163.100", 47 | "63.0.3239.132", 48 | "64.0.3282.0", 49 | "65.0.3325.146", 50 | "68.0.3440.106", 51 | "69.0.3497.100", 52 | "70.0.3538.102", 53 | "74.0.3729.169", 54 | } 55 | 56 | var operaVersions = []string{ 57 | "2.7.62 Version/11.00", 58 | "2.2.15 Version/10.10", 59 | "2.9.168 Version/11.50", 60 | "2.2.15 Version/10.00", 61 | "2.8.131 Version/11.11", 62 | "2.5.24 Version/10.54", 63 | } 64 | 65 | var osStrings = []string{ 66 | "Macintosh; Intel Mac OS X 10_10", 67 | "Windows NT 10.0", 68 | "Windows NT 5.1", 69 | "Windows NT 6.1; WOW64", 70 | "Windows NT 6.1; Win64; x64", 71 | "X11; Linux x86_64", 72 | } 73 | 74 | func genFirefoxUA() string { 75 | version := ffVersions[rand.Intn(len(ffVersions))] 76 | os := osStrings[rand.Intn(len(osStrings))] 77 | return fmt.Sprintf("Mozilla/5.0 (%s; rv:%.1f) Gecko/20100101 Firefox/%.1f", os, version, version) 78 | } 79 | 80 | func genChromeUA() string { 81 | version := chromeVersions[rand.Intn(len(chromeVersions))] 82 | os := osStrings[rand.Intn(len(osStrings))] 83 | return fmt.Sprintf("Mozilla/5.0 (%s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s Safari/537.36", os, version) 84 | } 85 | 86 | func genOperaUA() string { 87 | version := operaVersions[rand.Intn(len(operaVersions))] 88 | os := osStrings[rand.Intn(len(osStrings))] 89 | return fmt.Sprintf("Opera/9.80 (%s; U; en) Presto/%s", os, version) 90 | } 91 | -------------------------------------------------------------------------------- /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/blasting/rdpcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "github.com/bufsnake/Monkey/pkg/grdp" 6 | "log" 7 | "strings" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | type rdpcli struct { 13 | ip string 14 | port string 15 | } 16 | 17 | func (s *rdpcli) Info() string { 18 | return "weak" 19 | } 20 | 21 | func (m *rdpcli) Connect() (string, error) { 22 | usernames := []string{"woziniyaqi", "administrator", "admin", "test", "user", "manager", "webadmin", "guest", "db2admin"} 23 | passwords := []string{"R0ck9", "%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "Passw0rd", "admin123!@#", "admin", "admin123", "admin@123", "admin#123", "123456", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "postgres", "q1w2e3r4", "redhat", "user", "mysql", "apache"} 24 | wait := sync.WaitGroup{} 25 | messages := make(chan message, 600) 26 | fin := make(chan message) 27 | for i := 0; i < 5; i++ { 28 | wait.Add(1) 29 | go m.check(&wait, messages, fin) 30 | } 31 | for _, u := range usernames { 32 | for _, p := range passwords { 33 | messages <- message{ 34 | user: u, 35 | pass: p, 36 | } 37 | } 38 | } 39 | go func() { 40 | close(messages) 41 | wait.Wait() 42 | fin <- message{user: "error"} 43 | }() 44 | select { 45 | case <-time.After(5 * time.Minute): 46 | return "", errors.New("rdp weak password test timeout") 47 | case mess := <-fin: 48 | if mess.user == "error" { 49 | return "", errors.New("rdp weak password test finish,but no password found") 50 | } 51 | return "rdp://" + mess.user + ":" + mess.pass + "@" + m.ip + ":" + m.port, nil 52 | } 53 | } 54 | 55 | func (m *rdpcli) check(wg *sync.WaitGroup, messages chan message, fin chan message) { 56 | defer wg.Done() 57 | for message_ := range messages { 58 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 59 | err := grdp.Login(m.ip+":"+m.port, "", message_.user, message_.pass) 60 | if err != nil { 61 | log.Println("rdp cli blast error", message_.user, message_.pass, err) 62 | continue 63 | } 64 | fin <- message_ 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /pkg/blasting/ftpcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "github.com/jlaffaye/ftp" 6 | "log" 7 | "strings" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | type cliftp struct { 13 | ip string 14 | port string 15 | } 16 | 17 | func (f *cliftp) Info() string { 18 | return "weak" 19 | } 20 | 21 | func (f *cliftp) Connect() (string, error) { 22 | usernames := []string{"anonymous", "administrator", "ftp", "test", "admin", "web"} 23 | passwords := []string{"%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "Passw0rd", "admin123", "admin888", "administrator", "administrator123", "ftp", "ftppass", "123456", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "q1w2e3r4", "user", "mysql", "web", ""} 24 | wait := sync.WaitGroup{} 25 | messages := make(chan message, 600) 26 | fin := make(chan message) 27 | for i := 0; i < 5; i++ { 28 | wait.Add(1) 29 | go f.check(&wait, messages, fin) 30 | } 31 | for _, u := range usernames { 32 | for _, p := range passwords { 33 | messages <- message{ 34 | user: u, 35 | pass: p, 36 | } 37 | } 38 | } 39 | go func() { 40 | close(messages) 41 | wait.Wait() 42 | fin <- message{user: "error"} 43 | }() 44 | select { 45 | case <-time.After(5 * time.Minute): 46 | return "", errors.New("ftp weak password test timeout") 47 | case mess := <-fin: 48 | if mess.user == "error" { 49 | return "", errors.New("ftp weak password test finish,but no password found") 50 | } 51 | return "ftp://" + mess.user + ":" + mess.pass + "@" + f.ip + ":" + f.port, nil 52 | } 53 | } 54 | 55 | func (f *cliftp) check(wg *sync.WaitGroup, messages, fin chan message) { 56 | defer wg.Done() 57 | for message_ := range messages { 58 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 59 | c, err := ftp.Dial(f.ip+":"+f.port, ftp.DialWithTimeout(5*time.Second)) 60 | if err != nil { 61 | log.Println(err) 62 | continue 63 | } 64 | err = c.Login(message_.user, message_.pass) 65 | if err != nil { 66 | log.Println(err) 67 | continue 68 | } 69 | err = c.Quit() 70 | if err != nil { 71 | log.Println(err) 72 | continue 73 | } 74 | fin <- message_ 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /pkg/blasting/mssqlcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "fmt" 7 | "strings" 8 | "sync" 9 | "time" 10 | 11 | _ "github.com/denisenkom/go-mssqldb" 12 | ) 13 | 14 | type mssql struct { 15 | ip string 16 | port string 17 | } 18 | 19 | func (m *mssql) Info() string { 20 | return "weak" 21 | } 22 | 23 | func (m *mssql) Connect() (string, error) { 24 | usernames := []string{"sa"} 25 | passwords := []string{"admin", "%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "Passw0rd", "qweasdzxc", "admin123", "admin888", "administrator", "administrator123", "sa123", "ftp", "ftppass", "123456", "password", "12345", "1234", "sa", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "q1w2e3r4", "sqlpass", "sql123", "sqlserver", "web", ""} 26 | wait := sync.WaitGroup{} 27 | messages := make(chan message, 600) 28 | fin := make(chan message) 29 | for i := 0; i < 5; i++ { 30 | wait.Add(1) 31 | go m.check(&wait, messages, fin) 32 | } 33 | for _, u := range usernames { 34 | for _, p := range passwords { 35 | messages <- message{ 36 | user: u, 37 | pass: p, 38 | } 39 | } 40 | } 41 | go func() { 42 | close(messages) 43 | wait.Wait() 44 | fin <- message{user: "error"} 45 | }() 46 | select { 47 | case <-time.After(5 * time.Minute): 48 | return "", errors.New("mssql weak password test timeout") 49 | case mess := <-fin: 50 | if mess.user == "error" { 51 | return "", errors.New("mssql weak password test finish,but no password found") 52 | } 53 | return "mssql://" + mess.user + ":" + mess.pass + "@" + m.ip + ":" + m.port, nil 54 | } 55 | } 56 | 57 | func (m *mssql) check(wg *sync.WaitGroup, messages, fin chan message) { 58 | defer wg.Done() 59 | for message_ := range messages { 60 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 61 | db, err := sql.Open("mssql", fmt.Sprintf("server=%s;port=%s;user id=%s;password=%s;database=%s", m.ip, m.port, message_.user, message_.pass, "master")) 62 | if err != nil { 63 | fmt.Println(err) 64 | continue 65 | } 66 | err = db.Ping() 67 | if err != nil { 68 | fmt.Println(err) 69 | db.Close() 70 | continue 71 | } 72 | db.Close() 73 | fin <- message_ 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pkg/blasting/mysqlcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "github.com/ziutek/mymysql/mysql" 6 | "log" 7 | "strings" 8 | "sync" 9 | "time" 10 | 11 | _ "github.com/ziutek/mymysql/native" 12 | ) 13 | 14 | type climysql struct { 15 | ip string 16 | port string 17 | } 18 | 19 | func (m *climysql) Info() string { 20 | return "weak" 21 | } 22 | 23 | func (m *climysql) Connect() (string, error) { 24 | usernames := []string{"root"} 25 | passwords := []string{"%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "Passw0rd", "admin123", "admin888", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "123456qwerty", "password123", "1q2w3e", "okmnji", "test123", "test12345", "test123456", "q1w2e3r4", "mysql", "web", "%username%", "%null%", "123", "1234", "12345", "123456", "admin", "pass", "password", "!null!", "", "!user!", "", "1234567", "7654321", "abc123", "111111", "123321", "123123", "12345678", "123456789", "000000", "888888", "654321", "987654321", "147258369", "123asd", "qwer123", "P@ssw0rd", "root3306", "Q1W2E3b3", ""} 26 | wait := sync.WaitGroup{} 27 | messages := make(chan message, 600) 28 | fin := make(chan message) 29 | for i := 0; i < 5; i++ { 30 | wait.Add(1) 31 | go m.check(&wait, messages, fin) 32 | } 33 | for _, u := range usernames { 34 | for _, p := range passwords { 35 | messages <- message{ 36 | user: u, 37 | pass: p, 38 | } 39 | } 40 | } 41 | go func() { 42 | close(messages) 43 | wait.Wait() 44 | fin <- message{user: "error"} 45 | }() 46 | select { 47 | case <-time.After(5 * time.Minute): 48 | return "", errors.New("mysql weak password test timeout") 49 | case mess := <-fin: 50 | if mess.user == "error" { 51 | return "", errors.New("mysql weak password test finish,but no password found") 52 | } 53 | return "mysql://" + mess.user + ":" + mess.pass + "@" + m.ip + ":" + m.port, nil 54 | } 55 | } 56 | 57 | func (m *climysql) check(wg *sync.WaitGroup, messages, fin chan message) { 58 | defer wg.Done() 59 | for message_ := range messages { 60 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 61 | conn := mysql.New("tcp", "", m.ip+":"+m.port, message_.user, message_.pass, "mysql") 62 | conn.SetTimeout(5 * time.Second) 63 | err := conn.Connect() 64 | if err != nil { 65 | log.Println(err) 66 | continue 67 | } 68 | conn.Close() 69 | fin <- message_ 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/nla/cssp.go: -------------------------------------------------------------------------------- 1 | package nla 2 | 3 | import ( 4 | "encoding/asn1" 5 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 6 | ) 7 | 8 | type NegoToken struct { 9 | Data []byte `asn1:"explicit,tag:0"` 10 | } 11 | 12 | type TSRequest struct { 13 | Version int `asn1:"explicit,tag:0"` 14 | NegoTokens []NegoToken `asn1:"optional,explicit,tag:1"` 15 | AuthInfo []byte `asn1:"optional,explicit,tag:2"` 16 | PubKeyAuth []byte `asn1:"optional,explicit,tag:3"` 17 | //ErrorCode int `asn1:"optional,explicit,tag:4"` 18 | } 19 | 20 | type TSCredentials struct { 21 | CredType int `asn1:"explicit,tag:0"` 22 | Credentials []byte `asn1:"explicit,tag:1"` 23 | } 24 | 25 | type TSPasswordCreds struct { 26 | DomainName []byte `asn1:"explicit,tag:0"` 27 | UserName []byte `asn1:"explicit,tag:1"` 28 | Password []byte `asn1:"explicit,tag:2"` 29 | } 30 | 31 | type TSCspDataDetail struct { 32 | KeySpec int `asn1:"explicit,tag:0"` 33 | CardName string `asn1:"explicit,tag:1"` 34 | ReaderName string `asn1:"explicit,tag:2"` 35 | ContainerName string `asn1:"explicit,tag:3"` 36 | CspName string `asn1:"explicit,tag:4"` 37 | } 38 | 39 | type TSSmartCardCreds struct { 40 | Pin string `asn1:"explicit,tag:0"` 41 | CspData []TSCspDataDetail `asn1:"explicit,tag:1"` 42 | UserHint string `asn1:"explicit,tag:2"` 43 | DomainHint string `asn1:"explicit,tag:3"` 44 | } 45 | 46 | func EncodeDERTRequest(msgs []Message, authInfo []byte, pubKeyAuth []byte) []byte { 47 | req := TSRequest{ 48 | Version: 2, 49 | } 50 | 51 | if len(msgs) > 0 { 52 | req.NegoTokens = make([]NegoToken, 0, len(msgs)) 53 | } 54 | 55 | for _, msg := range msgs { 56 | token := NegoToken{msg.Serialize()} 57 | req.NegoTokens = append(req.NegoTokens, token) 58 | } 59 | 60 | if len(authInfo) > 0 { 61 | req.AuthInfo = authInfo 62 | } 63 | 64 | if len(pubKeyAuth) > 0 { 65 | req.PubKeyAuth = pubKeyAuth 66 | } 67 | 68 | result, err := asn1.Marshal(req) 69 | if err != nil { 70 | glog.Error(err) 71 | } 72 | return result 73 | } 74 | 75 | func DecodeDERTRequest(s []byte) (*TSRequest, error) { 76 | treq := &TSRequest{} 77 | _, err := asn1.Unmarshal(s, treq) 78 | return treq, err 79 | } 80 | func EncodeDERTCredentials(domain, username, password []byte) []byte { 81 | tpas := TSPasswordCreds{domain, username, password} 82 | result, err := asn1.Marshal(tpas) 83 | if err != nil { 84 | glog.Error(err) 85 | } 86 | tcre := TSCredentials{1, result} 87 | result, err = asn1.Marshal(tcre) 88 | if err != nil { 89 | glog.Error(err) 90 | } 91 | return result 92 | } 93 | 94 | func DecodeDERTCredentials(s []byte) (*TSCredentials, error) { 95 | tcre := &TSCredentials{} 96 | _, err := asn1.Unmarshal(s, tcre) 97 | return tcre, err 98 | } 99 | -------------------------------------------------------------------------------- /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/blasting/oraclecli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "fmt" 7 | _ "github.com/sijms/go-ora/v2" 8 | _ "github.com/ziutek/mymysql/native" 9 | "log" 10 | "strings" 11 | "sync" 12 | "time" 13 | ) 14 | 15 | type oraclecli struct { 16 | ip string 17 | port string 18 | } 19 | 20 | func (m *oraclecli) Info() string { 21 | return "weak" 22 | } 23 | 24 | func (m *oraclecli) Connect() (string, error) { 25 | usernames := []string{"sys", "system", "admin", "test", "web", "orcl"} 26 | passwords := []string{"R0ck9", "%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "Passw0rd", "admin", "sys", "system", "oracle", "dbadmin", "qweasdzxc", "admin123", "admin888", "administrator", "administrator123", "root123", "123456", "password", "12345", "root", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "q1w2e3r4"} 27 | wait := sync.WaitGroup{} 28 | messages := make(chan message, 600) 29 | fin := make(chan message) 30 | for i := 0; i < 5; i++ { 31 | wait.Add(1) 32 | go m.check(&wait, messages, fin) 33 | } 34 | for _, u := range usernames { 35 | for _, p := range passwords { 36 | messages <- message{ 37 | user: u, 38 | pass: p, 39 | } 40 | } 41 | } 42 | go func() { 43 | close(messages) 44 | wait.Wait() 45 | fin <- message{user: "error"} 46 | }() 47 | select { 48 | case <-time.After(5 * time.Minute): 49 | return "", errors.New("oracle weak password test timeout") 50 | case mess := <-fin: 51 | if mess.user == "error" { 52 | return "", errors.New("oracle weak password test finish,but no password found") 53 | } 54 | return "oracle://" + mess.user + ":" + mess.pass + "@" + m.ip + ":" + m.port, nil 55 | } 56 | } 57 | 58 | func (m *oraclecli) check(wg *sync.WaitGroup, messages, fin chan message) { 59 | defer wg.Done() 60 | for message_ := range messages { 61 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 62 | var db *sql.DB 63 | var err error 64 | for _, service := range []string{"ORCL", "XE", "ORACLE"} { 65 | db, err = sql.Open("oracle", fmt.Sprintf("oracle://%s:%s@%s:%s/%s", message_.user, message_.pass, m.ip, m.port, service)) 66 | if err == nil { 67 | break 68 | } 69 | } 70 | db.SetConnMaxLifetime(5 * time.Second) 71 | db.SetMaxIdleConns(0) 72 | err = db.Ping() 73 | if err != nil { 74 | log.Println(err) 75 | db.Close() 76 | continue 77 | } 78 | db.Close() 79 | fin <- message_ 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /pkg/blasting/smbcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "github.com/stacktitan/smb/smb" 6 | "log" 7 | "strconv" 8 | "strings" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | type clismb struct { 14 | ip string 15 | port string 16 | } 17 | 18 | func (s *clismb) Info() string { 19 | return "weak" 20 | } 21 | 22 | func (s *clismb) Connect() (string, error) { 23 | usernames := []string{"administrator", "admin", "test", "user", "manager", "webadmin", "guest", "db2admin"} 24 | passwords := []string{"%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "Passw0rd", "admin123!@#", "admin", "admin123", "admin@123", "admin#123", "123456", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "postgres", "q1w2e3r4", "redhat", "user", "mysql", "apache", ""} 25 | wait := sync.WaitGroup{} 26 | messages := make(chan message, 600) 27 | fin := make(chan message) 28 | for i := 0; i < 5; i++ { 29 | wait.Add(1) 30 | go s.check(&wait, messages, fin) 31 | } 32 | for _, u := range usernames { 33 | for _, p := range passwords { 34 | messages <- message{ 35 | user: u, 36 | pass: p, 37 | } 38 | } 39 | } 40 | go func() { 41 | close(messages) 42 | wait.Wait() 43 | fin <- message{user: "error"} 44 | }() 45 | select { 46 | case <-time.After(5 * time.Minute): 47 | return "", errors.New("smb weak password test timeout") 48 | case mess := <-fin: 49 | if mess.user == "error" { 50 | return "", errors.New("smb weak password test finish,but no password found") 51 | } 52 | return "smb://" + mess.user + ":" + mess.pass + "@" + s.ip + ":" + s.port, nil 53 | } 54 | } 55 | 56 | func (s *clismb) check(wg *sync.WaitGroup, messages, fin chan message) { 57 | defer wg.Done() 58 | for message_ := range messages { 59 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 60 | port, err := strconv.Atoi(s.port) 61 | if err != nil { 62 | log.Println(s.ip, s.port, err) 63 | continue 64 | } 65 | options := smb.Options{ 66 | Host: s.ip, 67 | Port: port, 68 | User: message_.user, 69 | Password: message_.pass, 70 | Domain: "", 71 | Workstation: "", 72 | } 73 | session, err := smb.NewSession(options, false) 74 | if err != nil { 75 | log.Println(err) 76 | continue 77 | } 78 | session.Close() 79 | if session.IsAuthenticated { 80 | fin <- message_ 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /pkg/blasting/mongodbcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "gopkg.in/mgo.v2" 7 | "log" 8 | "strings" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | type mongodb struct { 14 | ip string 15 | port string 16 | } 17 | 18 | // 方便判断是啥类型的漏洞 19 | func (s *mongodb) Info() string { 20 | return "weak" 21 | } 22 | 23 | func (m *mongodb) Connect() (string, error) { 24 | session, err := mgo.DialWithTimeout(fmt.Sprintf("mongodb://%s:%s/%s", m.ip, m.port, "test"), 2*time.Second) 25 | if err == nil { 26 | _, err := session.DatabaseNames() 27 | if err == nil { 28 | session.Close() 29 | return "mongodb://未授权@" + m.ip + ":" + m.port, nil 30 | } 31 | session.Close() 32 | } 33 | 34 | usernames := []string{"admin", "test", "system", "web"} 35 | passwords := []string{"123456", "admin", "mongodb", "%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "Passw0rd", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "admin123", "admin888", "administrator", "administrator123", "mongodb123", "mongodbpass", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "q1w2e3r4", "user", "web", ""} 36 | wait := sync.WaitGroup{} 37 | messages := make(chan message, 600) 38 | fin := make(chan message) 39 | for i := 0; i < 5; i++ { 40 | wait.Add(1) 41 | go m.check(&wait, messages, fin) 42 | } 43 | for _, u := range usernames { 44 | for _, p := range passwords { 45 | messages <- message{ 46 | user: u, 47 | pass: p, 48 | } 49 | } 50 | } 51 | go func() { 52 | close(messages) 53 | wait.Wait() 54 | fin <- message{user: "error"} 55 | }() 56 | select { 57 | case <-time.After(5 * time.Minute): 58 | return "", errors.New("mongodb weak password test timeout") 59 | case mess := <-fin: 60 | if mess.user == "error" { 61 | return "", errors.New("mongodb weak password test finish,but no password found") 62 | } 63 | return "mongodb://" + mess.user + ":" + mess.pass + "@" + m.ip + ":" + m.port, nil 64 | } 65 | } 66 | 67 | func (m *mongodb) check(wg *sync.WaitGroup, messages chan message, fin chan message) { 68 | defer wg.Done() 69 | for message_ := range messages { 70 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 71 | session, err := mgo.DialWithTimeout(fmt.Sprintf("mongodb://%s:%s@%s:%s/%s", message_.user, message_.pass, m.ip, m.port, "admin"), 10*time.Second) 72 | if err != nil { 73 | log.Println(err) 74 | continue 75 | } 76 | err = session.Ping() 77 | if err != nil { 78 | log.Println(err) 79 | session.Close() 80 | continue 81 | } 82 | session.Close() 83 | fin <- message_ 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /pkg/blasting/postgresqlcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | "fmt" 7 | "log" 8 | "strings" 9 | "sync" 10 | "time" 11 | 12 | _ "github.com/lib/pq" 13 | ) 14 | 15 | type postgresql struct { 16 | ip string 17 | port string 18 | } 19 | 20 | // 方便判断是啥类型的漏洞 21 | func (s *postgresql) Info() string { 22 | return "weak" 23 | } 24 | func (p *postgresql) Connect() (string, error) { 25 | db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s/%s?sslmode=%s", p.ip, p.port, "postgres", "disable")) 26 | if err == nil { 27 | _, err := db.Query("fjdaslfjaskldfjasl") 28 | if !strings.Contains(err.Error(), "authentication") && strings.Contains(err.Error(), "syntax error at or near") { 29 | err = db.Close() 30 | return "postgresql://未授权@" + p.ip + ":" + p.port, nil 31 | } 32 | err = db.Close() 33 | } 34 | 35 | usernames := []string{"postgres", "test", "admin", "web"} 36 | passwords := []string{"admin", "Passw0rd", "postgres", "%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "admin123", "admin888", "administrator", "administrator123", "root123", "ftp", "ftppass", "123456", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "q1w2e3r4", "user", "web", ""} 37 | wait := sync.WaitGroup{} 38 | messages := make(chan message, 600) 39 | fin := make(chan message) 40 | for i := 0; i < 5; i++ { 41 | wait.Add(1) 42 | go p.check(&wait, messages, fin) 43 | } 44 | for _, u := range usernames { 45 | for _, p := range passwords { 46 | messages <- message{ 47 | user: u, 48 | pass: p, 49 | } 50 | } 51 | } 52 | go func() { 53 | close(messages) 54 | wait.Wait() 55 | fin <- message{user: "error"} 56 | }() 57 | select { 58 | case <-time.After(5 * time.Minute): 59 | return "", errors.New("postgresql weak password test timeout") 60 | case mess := <-fin: 61 | if mess.user == "error" { 62 | return "", errors.New("postgresql weak password test finish,but no password found") 63 | } 64 | return "postgresql://" + mess.user + ":" + mess.pass + "@" + p.ip + ":" + p.port, nil 65 | } 66 | } 67 | 68 | func (p *postgresql) check(wg *sync.WaitGroup, messages, fin chan message) { 69 | defer wg.Done() 70 | for message_ := range messages { 71 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 72 | db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=%s", message_.user, message_.pass, p.ip, p.port, "postgres", "disable")) 73 | if err != nil { 74 | log.Println(err) 75 | continue 76 | } 77 | err = db.Ping() 78 | if err != nil { 79 | log.Println(err) 80 | db.Close() 81 | continue 82 | } 83 | db.Close() 84 | fin <- message_ 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /pkg/blasting/sshcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "golang.org/x/crypto/ssh" 7 | "log" 8 | "net" 9 | "strings" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | type clissh struct { 15 | ip string 16 | port string 17 | } 18 | 19 | func (s *clissh) Info() string { 20 | return "weak" 21 | } 22 | 23 | func (s *clissh) Connect() (string, error) { 24 | usernames := []string{"root", "jyhcg", "d5000", "ns5000", "test", "oracle", "admin", "user", "postgres", "mysql", "backup", "guest", "system", "web", "tomcat", "michael", "upload", "alex", "sys", "sales", "linux", "ftp", "temp", "nagios", "user1", "www", "test1", "eSER!@#"} 25 | passwords := []string{"%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "Passw0rd", "admin123!@#", "admin", "admin123", "admin@123", "admin#123", "123456", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "postgres", "q1w2e3r4", "redhat", "user", "mysql", "apache", "d5000", "ns5000", "jyhcg", ""} 26 | wait := sync.WaitGroup{} 27 | messages := make(chan message, 600) 28 | fin := make(chan message) 29 | for i := 0; i < 5; i++ { 30 | wait.Add(1) 31 | go s.check(&wait, messages, fin) 32 | } 33 | for _, u := range usernames { 34 | for _, p := range passwords { 35 | messages <- message{ 36 | user: u, 37 | pass: p, 38 | } 39 | } 40 | } 41 | go func() { 42 | close(messages) 43 | wait.Wait() 44 | fin <- message{user: "error"} 45 | }() 46 | select { 47 | case <-time.After(5 * time.Minute): 48 | return "", errors.New("ssh weak password test timeout") 49 | case mess := <-fin: 50 | if mess.user == "error" { 51 | return "", errors.New("ssh weak password test finish,but no password found") 52 | } 53 | return "ssh://" + mess.user + ":" + mess.pass + "@" + s.ip + ":" + s.port, nil 54 | } 55 | } 56 | 57 | func (s *clissh) check(wg *sync.WaitGroup, messages, fin chan message) { 58 | defer wg.Done() 59 | for message_ := range messages { 60 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 61 | var ( 62 | addr string 63 | clientConfig *ssh.ClientConfig 64 | err error 65 | ) 66 | clientConfig = &ssh.ClientConfig{ 67 | User: message_.user, 68 | Auth: []ssh.AuthMethod{ssh.Password(message_.pass)}, 69 | Timeout: 5 * time.Second, 70 | HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { 71 | return nil 72 | }, 73 | } 74 | clientConfig.Ciphers = []string{"aes128-cbc", "chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"} 75 | addr = fmt.Sprintf("%s:%s", s.ip, s.port) 76 | _, err = ssh.Dial("tcp", addr, clientConfig) 77 | if err != nil { 78 | log.Println(err) 79 | continue 80 | } 81 | fin <- message_ 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /cmd/Monkey/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "github.com/bufsnake/Monkey/config" 7 | "github.com/bufsnake/Monkey/internal/runner" 8 | "github.com/bufsnake/Monkey/pkg/log" 9 | "github.com/bufsnake/Monkey/pkg/parseip" 10 | "net" 11 | "os" 12 | "os/signal" 13 | "runtime" 14 | "strings" 15 | "syscall" 16 | ) 17 | 18 | func main() { 19 | runtime.GOMAXPROCS(runtime.NumCPU() * 3 / 4) 20 | var rLimit syscall.Rlimit 21 | rLimit.Max = 999999 22 | rLimit.Cur = 999999 23 | if runtime.GOOS == "darwin" { 24 | rLimit.Cur = 10240 25 | } 26 | err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) 27 | if err != nil { 28 | fmt.Println(err) 29 | os.Exit(1) 30 | } 31 | _ = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) 32 | 33 | addrs, err := net.InterfaceAddrs() 34 | if err != nil { 35 | fmt.Println(err) 36 | os.Exit(1) 37 | } 38 | localip := []string{} 39 | for _, address := range addrs { 40 | // 检查ip地址判断是否回环地址 41 | if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 42 | if ipnet.IP.To4() != nil { 43 | localip = append(localip, ipnet.IP.String()) 44 | } 45 | } 46 | } 47 | fmt.Println("Linux: sudo sysctl -w net.ipv4.ping_group_range=\"0 2147483647\"") 48 | fmt.Println("Local IP is", localip, ",ulimit -n is", rLimit.Cur) 49 | fmt.Println("内网扫描需要配置网关,网关IP为任意一台存活IP即可") 50 | conf := config.Config{} 51 | flag.StringVar(&conf.Target, "target", "", "specify target ip") 52 | flag.StringVar(&conf.Targets, "targets", "", "specify target ip from file") 53 | flag.IntVar(&conf.Thread, "thread", 6, "specify scan threads") 54 | flag.IntVar(&conf.Timeout, "timeout", 10, "web request timeout") 55 | flag.BoolVar(&conf.Blast, "blast", false, "blast service") 56 | flag.StringVar(&conf.NmapSV, "nmap-sv", "2", "nmap version intensity,optional 0~9") 57 | flag.StringVar(&conf.Port, "port", "0-65535", "specify scan ports") 58 | flag.StringVar(&conf.MasScanRate, "masscan-rate", "1000", "masscan rate") 59 | flag.Parse() 60 | if conf.Target == "" && conf.Targets == "" { 61 | flag.Usage() 62 | return 63 | } 64 | probes := make([][2]uint32, 0) 65 | if conf.Target != "" { 66 | start, end, err := parseip.ParseIP(conf.Target) 67 | if err != nil { 68 | fmt.Println(conf.Target, err) 69 | return 70 | } 71 | probes = append(probes, [2]uint32{start, end}) 72 | } else if conf.Targets != "" { 73 | file, err := os.ReadFile(conf.Targets) 74 | if err != nil { 75 | log.Println(err) 76 | return 77 | } 78 | split := strings.Split(string(file), "\n") 79 | for i := 0; i < len(split); i++ { 80 | split[i] = strings.Trim(split[i], "\r") 81 | if len(split[i]) == 0 { 82 | continue 83 | } 84 | start, end, err := parseip.ParseIP(split[i]) 85 | if err != nil { 86 | log.Println(err) 87 | return 88 | } 89 | probes = append(probes, [2]uint32{start, end}) 90 | } 91 | } 92 | 93 | var count uint32 94 | for i := 0; i < len(probes); i++ { 95 | count += probes[i][1] - probes[i][0] + 1 96 | } 97 | log.SetTotalCount(int(count)) 98 | go func() { 99 | c := make(chan os.Signal) 100 | signal.Notify(c, syscall.SIGTERM, syscall.SIGINT) 101 | select { 102 | case _ = <-c: 103 | fmt.Printf("\033[?25h") 104 | os.Exit(1) 105 | } 106 | }() 107 | runner.NewRunner(conf, probes).Run() 108 | fmt.Println() 109 | fmt.Printf("\033[?25h") 110 | } 111 | -------------------------------------------------------------------------------- /pkg/blasting/rediscli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "bufio" 5 | "errors" 6 | "fmt" 7 | "github.com/garyburd/redigo/redis" 8 | "log" 9 | "net" 10 | "strings" 11 | "sync" 12 | "time" 13 | ) 14 | 15 | type redis_cli struct { 16 | ip string 17 | port string 18 | } 19 | 20 | func (r *redis_cli) Info() string { 21 | return "weak" 22 | } 23 | 24 | func (r *redis_cli) Connect() (string, error) { 25 | conn, err := net.DialTimeout("tcp", r.ip+":"+r.port, 3*time.Second) 26 | if err != nil { 27 | log.Println("Redis Unauth Check Error", err) 28 | } else { 29 | conn.SetWriteDeadline(time.Now().Add(3 * time.Second)) 30 | _, err = conn.Write([]byte("info\r\n")) 31 | if err != nil { 32 | log.Println("Redis Unauth Check Error", err) 33 | } else { 34 | conn.SetReadDeadline(time.Now().Add(3 * time.Second)) 35 | reader := bufio.NewReader(conn) 36 | line, _ := reader.ReadString(byte('\n')) 37 | lines, _ := reader.ReadString(byte('\n')) 38 | liness, _ := reader.ReadString(byte('\n')) 39 | linesss, _ := reader.ReadString(byte('\n')) 40 | linessss, _ := reader.ReadString(byte('\n')) 41 | if strings.Contains(line+lines+liness+linesss+linessss, "redis_version") { 42 | return "redis://未授权@" + r.ip + ":" + r.port, nil 43 | } 44 | } 45 | conn.Close() 46 | } 47 | 48 | //usernames := []string{"admin", "redis", "root"} 49 | usernames := []string{""} 50 | passwords := []string{"Passw0rd", "admin", "%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "admin123", "admin888", "administrator", "administrator123", "root123", "123456", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "oracle", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "q1w2e3r4", "user", "web"} 51 | wait := sync.WaitGroup{} 52 | messages := make(chan message, 600) 53 | fin := make(chan message) 54 | for i := 0; i < 5; i++ { 55 | wait.Add(1) 56 | go r.check(&wait, messages, fin) 57 | } 58 | for _, u := range usernames { 59 | for _, p := range passwords { 60 | messages <- message{ 61 | user: u, 62 | pass: p, 63 | } 64 | } 65 | } 66 | go func() { 67 | close(messages) 68 | wait.Wait() 69 | fin <- message{user: "error"} 70 | }() 71 | select { 72 | case <-time.After(5 * time.Minute): 73 | return "", errors.New("redis weak password test timeout") 74 | case mess := <-fin: 75 | if mess.user == "error" { 76 | return "", errors.New("redis weak password test finish,but no password found") 77 | } 78 | return "redis://" + mess.pass + "@" + r.ip + ":" + r.port, nil 79 | } 80 | } 81 | 82 | func (r *redis_cli) check(wg *sync.WaitGroup, messages, fin chan message) { 83 | defer wg.Done() 84 | for message_ := range messages { 85 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 86 | c, err := redis.Dial("tcp", fmt.Sprintf("%s:%s", r.ip, r.port)) 87 | if err != nil { 88 | log.Println(err) 89 | continue 90 | } 91 | _, err = c.Do("AUTH", message_.pass) 92 | //flag := true 93 | //retry: 94 | // if flag { 95 | // } else { 96 | // _, err = c.Do("AUTH", message_.user, message_.pass) 97 | // } 98 | if err != nil { 99 | //if flag && strings.Contains(err.Error(), "WRONGPASS invalid username-password pair or user is disabled.") { 100 | // flag = false 101 | // goto retry 102 | //} 103 | log.Println(err) 104 | c.Close() 105 | continue 106 | } 107 | c.Close() 108 | fin <- message_ 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /pkg/log/main.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "fmt" 5 | . "github.com/logrusorgru/aurora" 6 | "math" 7 | "os" 8 | "strings" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | var totalcountbak float64 // 总数 14 | var totalcount float64 // 总数 15 | var increase float64 // 递增 16 | var schedule_lock sync.Mutex // 进度锁 17 | var ipalive map[string]int // IP存活数量 18 | var portnum int // 端口数量 19 | var errnum int // 失败数量 20 | var timestart time.Time // 开始时间 21 | 22 | var STOP = false 23 | 24 | func Bar() { 25 | for { 26 | if STOP { 27 | break 28 | } 29 | percentage := math.Trunc(((increase/totalcount)*100)*1e2) * 1e-2 // 更新进度条 30 | _, _ = fmt.Fprintf(os.Stdout, "\r\033[K\033[?25l%s %.0f %s %.2f%% %s %d %s %d %s %d %s %.2fs", BrightWhite("AllIP:").String(), totalcountbak, BrightWhite("Percentage:").String(), percentage, BrightWhite("IP:").String(), len(ipalive), BrightWhite("Port:").String(), portnum, BrightWhite("Err:").String(), errnum, BrightWhite("Time:").String(), time.Now().Sub(timestart).Seconds()) 31 | time.Sleep(1 * time.Second / 10) 32 | } 33 | } 34 | 35 | // 首先根据IP数量设置totalcount 36 | func SetTotalCount(ipcount int) { 37 | totalcount = float64(ipcount) 38 | totalcountbak = float64(ipcount) 39 | timestart = time.Now() 40 | ipalive = make(map[string]int) 41 | portnum = 0 42 | errnum = 0 43 | } 44 | 45 | func UpdateTotalCount(portcount int) { 46 | schedule_lock.Lock() 47 | defer schedule_lock.Unlock() 48 | totalcount += float64(portcount - 1) 49 | percentage := math.Trunc(((increase/totalcount)*100)*1e2) * 1e-2 // 更新进度条 50 | fmt.Printf("\r%s %.0f %s %.2f%% %s %d %s %d %s %d %s %.2fs ", BrightWhite("AllIP:").String(), totalcountbak, BrightWhite("Percentage:").String(), percentage, BrightWhite("IP:").String(), len(ipalive), BrightWhite("Port:").String(), portnum, BrightWhite("Err:").String(), errnum, BrightWhite("Time:").String(), time.Now().Sub(timestart).Seconds()) 51 | } 52 | 53 | // Terminal == IP PORT PROTOCOL VERSION 54 | // 进度: Percentage IP存活: IPAliveNum 端口数量: PortNum 当前耗时: xxxx 55 | func Println(a ...interface{}) { 56 | schedule_lock.Lock() 57 | defer schedule_lock.Unlock() 58 | increase++ 59 | terminal := []interface{}{} 60 | err := false 61 | for i := 0; i < len(a); i++ { 62 | if i == 4 { 63 | break 64 | } 65 | if i == 0 { 66 | terminal = append(terminal, "\r"+color(i, a[i])) 67 | } else { 68 | terminal = append(terminal, color(i, a[i])) 69 | } 70 | if strings.Contains(color(i, a[i]), "not found port") { 71 | err = true 72 | } 73 | } 74 | if len(a) > 2 { 75 | ipalive[color(0, a[0])] = 1 76 | portnum++ 77 | if len(terminal) == 4 { 78 | if len(color(3, a[3])) < 30+9 { 79 | terminal = append(terminal, strings.Repeat(" ", 30)) 80 | } 81 | 82 | } 83 | } else { 84 | errnum++ 85 | terminal = append(terminal, strings.Repeat(" ", 30)) 86 | } 87 | if !err { 88 | fmt.Println(terminal...) 89 | } 90 | if totalcount == 0 { 91 | return 92 | } 93 | percentage := math.Trunc(((increase/totalcount)*100)*1e2) * 1e-2 // 更新进度条 94 | fmt.Printf("\r%s %.0f %s %.2f%% %s %d %s %d %s %d %s %.2fs ", BrightWhite("AllIP:").String(), totalcountbak, BrightWhite("Percentage:").String(), percentage, BrightWhite("IP:").String(), len(ipalive), BrightWhite("Port:").String(), portnum, BrightWhite("Err:").String(), errnum, BrightWhite("Time:").String(), time.Now().Sub(timestart).Seconds()) 95 | } 96 | 97 | func color(i int, data interface{}) string { 98 | switch i { 99 | case 0: // IP 100 | return fmt.Sprintf("%-25s", BrightGreen(data).String()) 101 | case 1: // PORT 102 | return fmt.Sprintf("%-14s", BrightCyan(data).String()) 103 | case 2: // PROTOCOL 104 | return fmt.Sprintf("%-34s", BrightMagenta(data).String()) 105 | case 3: // VERSION 106 | return fmt.Sprintf("%s", BrightYellow(data).String()) 107 | default: 108 | return BrightWhite(data).String() 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /pkg/sitescan/request.go: -------------------------------------------------------------------------------- 1 | package sitescan 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "github.com/bufsnake/Monkey/pkg/useragent" 7 | "golang.org/x/text/encoding/simplifiedchinese" 8 | "golang.org/x/text/transform" 9 | "html" 10 | "io/ioutil" 11 | "net/http" 12 | "regexp" 13 | "strings" 14 | "time" 15 | ) 16 | 17 | type request struct { 18 | url string 19 | timeout int 20 | title string 21 | middleware string 22 | xpoweredby string 23 | code int 24 | length int 25 | header map[string]string 26 | product string 27 | } 28 | 29 | func (r *request) Run() error { 30 | client := http.Client{ 31 | Transport: &http.Transport{ 32 | TLSClientConfig: &tls.Config{ 33 | InsecureSkipVerify: true, 34 | }, 35 | DisableKeepAlives: true, 36 | }, 37 | Timeout: time.Duration(r.timeout) * time.Second, 38 | // 禁止301/302跳转 39 | CheckRedirect: func(req *http.Request, via []*http.Request) error { 40 | return http.ErrUseLastResponse 41 | }, 42 | } 43 | req, err := http.NewRequest("GET", r.url, nil) 44 | if err != nil { 45 | return err 46 | } 47 | req.Header.Set("USER-AGENT", useragent.RandomUserAgent()) 48 | req.Header.Set("Connection", "close") 49 | req.Header.Set("rememberMe", "xxxxxxxxxxxxxxx") 50 | do, err := client.Do(req) 51 | if err != nil { 52 | return err 53 | } 54 | defer do.Body.Close() 55 | body, err := ioutil.ReadAll(do.Body) 56 | if err != nil { 57 | return err 58 | } 59 | r.length = len(body) 60 | r.code = do.StatusCode 61 | r.title, err = extracttitle(string(body)) 62 | if err != nil { 63 | r.title = "None" 64 | } 65 | r.title = strings.Trim(r.title, " \t\r") 66 | r.header = make(map[string]string) 67 | for key, value := range do.Header { 68 | val := "" 69 | for i := 0; i < len(value); i++ { 70 | val += value[i] + " " 71 | } 72 | r.header[key] = strings.ToLower(val) 73 | } 74 | r.middleware = r.GetServer() 75 | r.xpoweredby = r.GetXPoweredBy() 76 | return nil 77 | } 78 | 79 | func (r *request) GetHeader(key string) string { 80 | for v, k := range r.header { 81 | if strings.ToLower(v) == strings.ToLower(key) { 82 | return k 83 | } 84 | } 85 | return "" 86 | } 87 | 88 | func (r *request) GetTitle() string { 89 | return r.title 90 | } 91 | 92 | func (r *request) GetServer() string { 93 | return r.GetHeader("Server") 94 | } 95 | 96 | func (r *request) GetXPoweredBy() string { 97 | return r.GetHeader("X-Powered-By") 98 | } 99 | 100 | func (r *request) GetCode() int { 101 | return r.code 102 | } 103 | 104 | func (r *request) GetLength() int { 105 | return r.length 106 | } 107 | 108 | func (r *request) GetUrl() string { 109 | return r.url 110 | } 111 | 112 | // 获取网站标题 113 | func extracttitle(body string) (string, error) { 114 | title := "" 115 | var re = regexp.MustCompile(`(?im)<\s*title.*>(.*?)<\s*/\s*title>`) 116 | for _, match := range re.FindAllString(body, -1) { 117 | title = html.UnescapeString(trimTitleTags(match)) 118 | break 119 | } 120 | if !validUTF8([]byte(title)) { 121 | reader := transform.NewReader(bytes.NewReader([]byte(title)), simplifiedchinese.GBK.NewDecoder()) 122 | d, err := ioutil.ReadAll(reader) 123 | if err != nil { 124 | return title, err 125 | } 126 | return string(d), nil 127 | } 128 | return title, nil 129 | } 130 | 131 | func trimTitleTags(title string) string { 132 | titleBegin := strings.Index(title, ">") 133 | titleEnd := strings.Index(title, " 6 { //因为UTF8编码单字符最多不超过6个字节 148 | return false 149 | } 150 | 151 | nBytes-- //减掉首字节的一个计数 152 | } 153 | } else { //处理多字节字符 154 | if buf[i]&0xc0 != 0x80 { //判断多字节后面的字节是否是10开头 155 | return false 156 | } 157 | nBytes-- 158 | } 159 | } 160 | return nBytes == 0 161 | } 162 | -------------------------------------------------------------------------------- /internal/runner/main.go: -------------------------------------------------------------------------------- 1 | package runner 2 | 3 | import ( 4 | "fmt" 5 | "github.com/bufsnake/Monkey/config" 6 | "github.com/bufsnake/Monkey/pkg/blasting" 7 | "github.com/bufsnake/Monkey/pkg/log" 8 | "github.com/bufsnake/Monkey/pkg/parseip" 9 | "github.com/bufsnake/Monkey/pkg/portscan" 10 | "github.com/bufsnake/Monkey/pkg/sitescan" 11 | "strings" 12 | "sync" 13 | "time" 14 | ) 15 | 16 | type Runner struct { 17 | conf config.Config 18 | probes [][2]uint32 19 | services map[string][]portscan.Service 20 | } 21 | 22 | func NewRunner(conf config.Config, probes [][2]uint32) *Runner { 23 | return &Runner{conf: conf, probes: probes, services: make(map[string][]portscan.Service)} 24 | } 25 | 26 | func (c *Runner) Run() { 27 | go log.Bar() 28 | 29 | // 端口扫描 30 | portwait := sync.WaitGroup{} 31 | portchan := make(chan string, c.conf.Thread) 32 | for i := 0; i < c.conf.Thread; i++ { 33 | portwait.Add(1) 34 | go c.portscan(&portwait, portchan) 35 | } 36 | m := make(map[uint32]bool) 37 | for i := 0; i < len(c.probes); i++ { 38 | for j := c.probes[i][0]; j <= c.probes[i][1]; j++ { 39 | if _, ok := m[j]; ok { 40 | continue 41 | } 42 | portchan <- parseip.UInt32ToIP(j) 43 | } 44 | } 45 | close(portchan) 46 | portwait.Wait() 47 | 48 | log.STOP = true 49 | time.Sleep(time.Second) 50 | 51 | fmt.Println() 52 | // HTTP服务探测 53 | fmt.Println("HTTP:") 54 | var n_weak = []string{"SSH", "SSL/SSH", "FTP", "SSL/FTP", "MYSQL", "NAGIOS-NSCA", "SSL/MYSQL", "SSL/NAGIOS-NSCA", "MS-SQL-S", "SSL/MS-SQL-S", "REDIS", "SSL/REDIS", "MONGOD", "SSL/MONGOD", "MONGODB", "SSL/MONGODB", "POSTGRESQL", "SSL/POSTGRESQL", "MICROSOFT-DS", "SSL/MICROSOFT-DS", "SNMP", "SSL/SNMP", "DOCKER", "SSL/DOCKER", "ZOOKEEPER", "SSL/ZOOKEEPER", "MEMCACHE", "SSL/MEMCACHE", "MS-WBT-SERVER", "SSL/MS-WBT-SERVER", "TELNET", "SSL/TELNET", "ORACLE", "SSL/ORACLE", "DOCKER", "ZOOKEEPER", "MEMCACHED"} 55 | for ip, services := range c.services { 56 | for i := 0; i < len(services); i++ { 57 | if c.conf.Blast && c.exist(n_weak, strings.ToUpper(strings.Trim(services[i].Protocol, "?")), true) { 58 | continue 59 | } 60 | // HTTP 探测 61 | httpx := sitescan.NewHttpx(ip+":"+services[i].Port, c.conf.Timeout) 62 | err := httpx.Run() 63 | if err != nil { 64 | continue 65 | } 66 | for j := 0; j < len(httpx.URLS); j++ { 67 | fmt.Println(httpx.URLS[j].GetUrl()) 68 | } 69 | } 70 | } 71 | if c.conf.Blast { 72 | fmt.Println("WEAK PASSWORD:") 73 | } 74 | // 弱口令扫描 75 | for ip, services := range c.services { 76 | for i := 0; i < len(services); i++ { 77 | if !c.conf.Blast || c.exist(n_weak, strings.ToUpper(strings.Trim(services[i].Protocol, "?")), true) { 78 | continue 79 | } 80 | // 弱口令探测 81 | blast, err := blasting.NewBlast(strings.Trim(services[i].Protocol, "?"), ip, services[i].Port) 82 | if err != nil { 83 | continue 84 | } 85 | weakurl, err := blast.Connect() 86 | if err != nil { 87 | continue 88 | } 89 | fmt.Println(weakurl) 90 | } 91 | } 92 | // 全部端口 93 | mx := make(map[string]bool) 94 | ports := make([]string, 0) 95 | for _, services := range c.services { 96 | for i := 0; i < len(services); i++ { 97 | if _, ok := mx[services[i].Port]; ok { 98 | continue 99 | } 100 | mx[services[i].Port] = true 101 | ports = append(ports, services[i].Port) 102 | } 103 | } 104 | if len(ports) == 0 { 105 | return 106 | } 107 | fmt.Print("PORTS:\n" + strings.Join(ports, ",")) 108 | } 109 | 110 | // strong 强判断 111 | func (c *Runner) exist(arr []string, data string, strong bool) bool { 112 | for i := 0; i < len(arr); i++ { 113 | if strong { 114 | if arr[i] == data { 115 | return true 116 | } 117 | } else if strings.Contains(data, arr[i]) { 118 | return true 119 | } 120 | } 121 | return false 122 | } 123 | 124 | func (c *Runner) portscan(wait *sync.WaitGroup, portchan chan string) { 125 | defer wait.Done() 126 | for ip := range portchan { 127 | scan := portscan.NewPortScan(c.conf) 128 | err := scan.PortScan(ip) 129 | if err != nil { 130 | log.Println(ip, err.Error()+strings.Repeat(" ", 18)) 131 | continue 132 | } 133 | services := scan.GetService() 134 | log.UpdateTotalCount(len(services)) 135 | for i := 0; i < len(services); i++ { 136 | port, protocol, version := services[i].Port, services[i].Protocol, services[i].Version 137 | if strings.TrimSpace(services[i].ServiceFP) != "" { 138 | protocol = strings.Trim(protocol, "?") + "?" 139 | } 140 | log.Println(ip, port, protocol, version) 141 | } 142 | if _, ok := c.services[ip]; !ok { 143 | c.services[ip] = make([]portscan.Service, 0) 144 | } 145 | c.services[ip] = append(c.services[ip], services...) 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/t125/per/per.go: -------------------------------------------------------------------------------- 1 | package per 2 | 3 | import ( 4 | "bytes" 5 | "github.com/bufsnake/Monkey/pkg/grdp/core" 6 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 7 | "io" 8 | ) 9 | 10 | func ReadEnumerates(r io.Reader) (uint8, error) { 11 | return core.ReadUInt8(r) 12 | } 13 | 14 | func WriteInteger(n int, w io.Writer) { 15 | if n <= 0xff { 16 | WriteLength(1, w) 17 | core.WriteUInt8(uint8(n), w) 18 | } else if n <= 0xffff { 19 | WriteLength(2, w) 20 | core.WriteUInt16BE(uint16(n), w) 21 | } else { 22 | WriteLength(4, w) 23 | core.WriteUInt32BE(uint32(n), w) 24 | } 25 | } 26 | 27 | func ReadInteger16(r io.Reader) (uint16, error) { 28 | return core.ReadUint16BE(r) 29 | } 30 | 31 | func WriteInteger16(value uint16, w io.Writer) { 32 | core.WriteUInt16BE(value, w) 33 | } 34 | 35 | /** 36 | * @param choice {integer} 37 | * @returns {type.UInt8} choice per encoded 38 | */ 39 | func WriteChoice(choice uint8, w io.Writer) { 40 | core.WriteUInt8(choice, w) 41 | } 42 | 43 | /** 44 | * @param value {raw} value to convert to per format 45 | * @returns type objects per encoding value 46 | */ 47 | func WriteLength(value int, w io.Writer) { 48 | if value > 0x7f { 49 | core.WriteUInt16BE(uint16(value|0x8000), w) 50 | } else { 51 | core.WriteUInt8(uint8(value), w) 52 | } 53 | } 54 | 55 | func ReadLength(r io.Reader) (uint16, error) { 56 | b, err := core.ReadUInt8(r) 57 | if err != nil { 58 | return 0, nil 59 | } 60 | var size uint16 61 | if b&0x80 > 0 { 62 | b = b &^ 0x80 63 | size = uint16(b) << 8 64 | left, _ := core.ReadUInt8(r) 65 | size += uint16(left) 66 | } else { 67 | size = uint16(b) 68 | } 69 | return size, nil 70 | } 71 | 72 | /** 73 | * @param oid {array} oid to write 74 | * @returns {type.Component} per encoded object identifier 75 | */ 76 | func WriteObjectIdentifier(oid []byte, w io.Writer) { 77 | core.WriteUInt8(5, w) 78 | core.WriteByte((oid[0]<<4)&(oid[1]&0x0f), w) 79 | core.WriteByte(oid[2], w) 80 | core.WriteByte(oid[3], w) 81 | core.WriteByte(oid[4], w) 82 | core.WriteByte(oid[5], w) 83 | } 84 | 85 | /** 86 | * @param selection {integer} 87 | * @returns {type.UInt8} per encoded selection 88 | */ 89 | func WriteSelection(selection uint8, w io.Writer) { 90 | core.WriteUInt8(selection, w) 91 | } 92 | 93 | func WriteNumericString(s string, minValue int, w io.Writer) { 94 | length := len(s) 95 | mLength := minValue 96 | if length >= minValue { 97 | mLength = length - minValue 98 | } 99 | buff := &bytes.Buffer{} 100 | for i := 0; i < length; i += 2 { 101 | c1 := int(s[i]) 102 | c2 := 0x30 103 | if i+1 < length { 104 | c2 = int(s[i+1]) 105 | } 106 | c1 = (c1 - 0x30) % 10 107 | c2 = (c2 - 0x30) % 10 108 | core.WriteUInt8(uint8((c1<<4)|c2), buff) 109 | } 110 | WriteLength(mLength, w) 111 | w.Write(buff.Bytes()) 112 | } 113 | 114 | func WritePadding(length int, w io.Writer) { 115 | b := make([]byte, length) 116 | w.Write(b) 117 | } 118 | 119 | func WriteNumberOfSet(n int, w io.Writer) { 120 | core.WriteUInt8(uint8(n), w) 121 | } 122 | 123 | /** 124 | * @param oStr {String} 125 | * @param minValue {integer} default 0 126 | * @returns {type.Component} per encoded octet stream 127 | */ 128 | func WriteOctetStream(oStr string, minValue int, w io.Writer) { 129 | length := len(oStr) 130 | mlength := minValue 131 | 132 | if length-minValue >= 0 { 133 | mlength = length - minValue 134 | } 135 | WriteLength(mlength, w) 136 | w.Write([]byte(oStr)[:length]) 137 | } 138 | 139 | func ReadChoice(r io.Reader) uint8 { 140 | choice, _ := core.ReadUInt8(r) 141 | return choice 142 | } 143 | func ReadNumberOfSet(r io.Reader) uint8 { 144 | choice, _ := core.ReadUInt8(r) 145 | return choice 146 | } 147 | func ReadInteger(r io.Reader) uint32 { 148 | size, _ := ReadLength(r) 149 | switch size { 150 | case 1: 151 | ret, _ := core.ReadUInt8(r) 152 | return uint32(ret) 153 | case 2: 154 | ret, _ := core.ReadUint16BE(r) 155 | return uint32(ret) 156 | case 4: 157 | ret, _ := core.ReadUInt32BE(r) 158 | return ret 159 | default: 160 | glog.Info("ReadInteger") 161 | } 162 | return 0 163 | } 164 | 165 | func ReadObjectIdentifier(r io.Reader, oid []byte) bool { 166 | size, _ := ReadLength(r) 167 | if size != 5 { 168 | return false 169 | } 170 | 171 | a_oid := []byte{0, 0, 0, 0, 0, 0} 172 | t12, _ := core.ReadByte(r) 173 | a_oid[0] = t12 >> 4 174 | a_oid[1] = t12 & 0x0f 175 | a_oid[2], _ = core.ReadByte(r) 176 | a_oid[3], _ = core.ReadByte(r) 177 | a_oid[4], _ = core.ReadByte(r) 178 | a_oid[5], _ = core.ReadByte(r) 179 | 180 | for i, _ := range oid { 181 | if oid[i] != a_oid[i] { 182 | return false 183 | } 184 | } 185 | return true 186 | } 187 | func ReadOctetStream(r io.Reader, s string, min int) bool { 188 | ln, _ := ReadLength(r) 189 | size := int(ln) + min 190 | if size != len(s) { 191 | return false 192 | } 193 | for i := 0; i < size; i++ { 194 | b, _ := core.ReadByte(r) 195 | if b != s[i] { 196 | return false 197 | } 198 | } 199 | 200 | return true 201 | } 202 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/t125/ber/ber.go: -------------------------------------------------------------------------------- 1 | package ber 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/bufsnake/Monkey/pkg/grdp/core" 7 | "io" 8 | ) 9 | 10 | const ( 11 | CLASS_MASK uint8 = 0xC0 12 | CLASS_UNIV = 0x00 13 | CLASS_APPL = 0x40 14 | CLASS_CTXT = 0x80 15 | CLASS_PRIV = 0xC0 16 | ) 17 | 18 | const ( 19 | PC_MASK uint8 = 0x20 20 | PC_PRIMITIVE = 0x00 21 | PC_CONSTRUCT = 0x20 22 | ) 23 | 24 | const ( 25 | TAG_MASK uint8 = 0x1F 26 | TAG_BOOLEAN = 0x01 27 | TAG_INTEGER = 0x02 28 | TAG_BIT_STRING = 0x03 29 | TAG_OCTET_STRING = 0x04 30 | TAG_OBJECT_IDENFIER = 0x06 31 | TAG_ENUMERATED = 0x0A 32 | TAG_SEQUENCE = 0x10 33 | TAG_SEQUENCE_OF = 0x10 34 | ) 35 | 36 | func berPC(pc bool) uint8 { 37 | if pc { 38 | return PC_CONSTRUCT 39 | } 40 | return PC_PRIMITIVE 41 | } 42 | 43 | func ReadEnumerated(r io.Reader) (uint8, error) { 44 | if !ReadUniversalTag(TAG_ENUMERATED, false, r) { 45 | return 0, errors.New("invalid ber tag") 46 | } 47 | length, err := ReadLength(r) 48 | if err != nil { 49 | return 0, err 50 | } 51 | if length != 1 { 52 | return 0, errors.New(fmt.Sprintf("enumerate size is wrong, get %v, expect 1", length)) 53 | } 54 | return core.ReadUInt8(r) 55 | } 56 | 57 | func ReadUniversalTag(tag uint8, pc bool, r io.Reader) bool { 58 | bb, _ := core.ReadUInt8(r) 59 | return bb == (CLASS_UNIV|berPC(pc))|(TAG_MASK&tag) 60 | } 61 | 62 | func WriteUniversalTag(tag uint8, pc bool, w io.Writer) { 63 | core.WriteUInt8((CLASS_UNIV|berPC(pc))|(TAG_MASK&tag), w) 64 | } 65 | 66 | func ReadLength(r io.Reader) (int, error) { 67 | ret := 0 68 | size, _ := core.ReadUInt8(r) 69 | if size&0x80 > 0 { 70 | size = size &^ 0x80 71 | if size == 1 { 72 | r, err := core.ReadUInt8(r) 73 | if err != nil { 74 | return 0, err 75 | } 76 | ret = int(r) 77 | } else if size == 2 { 78 | r, err := core.ReadUint16BE(r) 79 | if err != nil { 80 | return 0, err 81 | } 82 | ret = int(r) 83 | } else { 84 | return 0, errors.New("BER length may be 1 or 2") 85 | } 86 | } else { 87 | ret = int(size) 88 | } 89 | return ret, nil 90 | } 91 | 92 | func WriteLength(size int, w io.Writer) { 93 | if size > 0x7f { 94 | core.WriteUInt8(0x82, w) 95 | core.WriteUInt16BE(uint16(size), w) 96 | } else { 97 | core.WriteUInt8(uint8(size), w) 98 | } 99 | } 100 | 101 | func ReadInteger(r io.Reader) (int, error) { 102 | if !ReadUniversalTag(TAG_INTEGER, false, r) { 103 | return 0, errors.New("Bad integer tag") 104 | } 105 | size, _ := ReadLength(r) 106 | switch size { 107 | case 1: 108 | num, _ := core.ReadUInt8(r) 109 | return int(num), nil 110 | case 2: 111 | num, _ := core.ReadUint16BE(r) 112 | return int(num), nil 113 | case 3: 114 | integer1, _ := core.ReadUInt8(r) 115 | integer2, _ := core.ReadUint16BE(r) 116 | return int(integer2) + int(integer1<<16), nil 117 | case 4: 118 | num, _ := core.ReadUInt32BE(r) 119 | return int(num), nil 120 | default: 121 | return 0, errors.New("wrong size") 122 | } 123 | } 124 | 125 | func WriteInteger(n int, w io.Writer) { 126 | WriteUniversalTag(TAG_INTEGER, false, w) 127 | if n <= 0xff { 128 | WriteLength(1, w) 129 | core.WriteUInt8(uint8(n), w) 130 | } else if n <= 0xffff { 131 | WriteLength(2, w) 132 | core.WriteUInt16BE(uint16(n), w) 133 | } else { 134 | WriteLength(4, w) 135 | core.WriteUInt32BE(uint32(n), w) 136 | } 137 | } 138 | 139 | func WriteOctetstring(str string, w io.Writer) { 140 | WriteUniversalTag(TAG_OCTET_STRING, false, w) 141 | WriteLength(len(str), w) 142 | core.WriteBytes([]byte(str), w) 143 | } 144 | 145 | func WriteBoolean(b bool, w io.Writer) { 146 | bb := uint8(0) 147 | if b { 148 | bb = uint8(0xff) 149 | } 150 | WriteUniversalTag(TAG_BOOLEAN, false, w) 151 | WriteLength(1, w) 152 | core.WriteUInt8(bb, w) 153 | } 154 | 155 | func ReadApplicationTag(tag uint8, r io.Reader) (int, error) { 156 | bb, _ := core.ReadUInt8(r) 157 | if tag > 30 { 158 | if bb != (CLASS_APPL|PC_CONSTRUCT)|TAG_MASK { 159 | return 0, errors.New("ReadApplicationTag invalid data") 160 | } 161 | bb, _ := core.ReadUInt8(r) 162 | if bb != tag { 163 | return 0, errors.New("ReadApplicationTag bad tag") 164 | } 165 | } else { 166 | if bb != (CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag) { 167 | return 0, errors.New("ReadApplicationTag invalid data2") 168 | } 169 | } 170 | return ReadLength(r) 171 | } 172 | 173 | func WriteApplicationTag(tag uint8, size int, w io.Writer) { 174 | if tag > 30 { 175 | core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|TAG_MASK, w) 176 | core.WriteUInt8(tag, w) 177 | WriteLength(size, w) 178 | } else { 179 | core.WriteUInt8((CLASS_APPL|PC_CONSTRUCT)|(TAG_MASK&tag), w) 180 | WriteLength(size, w) 181 | } 182 | } 183 | 184 | func WriteEncodedDomainParams(data []byte, w io.Writer) { 185 | WriteUniversalTag(TAG_SEQUENCE, true, w) 186 | WriteLength(len(data), w) 187 | core.WriteBytes(data, w) 188 | } 189 | -------------------------------------------------------------------------------- /pkg/parseip/main.go: -------------------------------------------------------------------------------- 1 | package parseip 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | // 支持常见的ip格式 12 | // 192.168.113.159 13 | // 192.168.113.159-254 14 | // 192.168.113.159-192.168.113.254 15 | // 192.168.113.0/24 16 | // 191.168.113.159-192.168.114.254 17 | // 192.167.113.159-192.168.114.254 18 | // 192.168.113.159-192.168.114.254 19 | func ParseIP(ip string) (startx uint32, endx uint32, err error) { 20 | ip = strings.TrimSpace(ip) 21 | if strings.Contains(ip, "-") { 22 | if len(strings.Split(ip, "-")[1]) <= 3 { 23 | return multipleip(ip) 24 | } else { 25 | return multipleip2(ip) 26 | } 27 | } else if strings.Contains(ip, "/") { 28 | return multipleip3(ip) 29 | } else { 30 | return singleip(ip) 31 | } 32 | } 33 | 34 | // 192.168.113.159 35 | func singleip(ip string) (startx uint32, endx uint32, err error) { 36 | for _, val := range strings.Split(ip, ".") { 37 | ips, err := strconv.Atoi(val) 38 | if err != nil { 39 | return 0, 0, errors.New(ip + " " + err.Error() + " ip parse error") 40 | } 41 | if ips > 255 { 42 | return 0, 0, errors.New(ip + " ip parse error") 43 | } 44 | } 45 | startx, err = ip2UInt32(ip) 46 | if err != nil { 47 | return 0, 0, err 48 | } 49 | endx, err = ip2UInt32(ip) 50 | if err != nil { 51 | return 0, 0, err 52 | } 53 | return startx, endx, nil 54 | } 55 | 56 | // 192.168.113.159-255 57 | func multipleip(ips string) (startx uint32, endx uint32, err error) { 58 | host := strings.Split(ips, "-") 59 | ip := host[0] 60 | if len(strings.Split(ip, ".")) != 4 { 61 | return 0, 0, errors.New("multipleip error " + ips) 62 | } 63 | start, err := strconv.Atoi(strings.Split(ip, ".")[3]) 64 | if err != nil { 65 | return 0, 0, errors.New(ips + " " + err.Error() + " ip parse error") 66 | } 67 | end, err := strconv.Atoi(host[1]) 68 | if err != nil { 69 | return 0, 0, errors.New(ips + " " + err.Error() + " ip parse error") 70 | } 71 | if start > end { 72 | return 0, 0, errors.New(ips + " ip parse error") 73 | } 74 | if start < 0 { 75 | start = 0 76 | } 77 | if end > 255 { 78 | end = 255 79 | } 80 | temp := strings.Split(ip, ".") 81 | start_t, err := ip2UInt32(temp[0] + "." + temp[1] + "." + temp[2] + "." + strconv.Itoa(start)) 82 | if err != nil { 83 | return 0, 0, err 84 | } 85 | end_t, err := ip2UInt32(temp[0] + "." + temp[1] + "." + temp[2] + "." + strconv.Itoa(end)) 86 | if err != nil { 87 | return 0, 0, err 88 | } 89 | return start_t, end_t, nil 90 | } 91 | 92 | // 192.168.113.159-192.168.113.254 93 | func multipleip2(ips string) (startx uint32, endx uint32, err error) { 94 | start, err := ip2UInt32(strings.Split(ips, "-")[0]) 95 | if err != nil { 96 | return 0, 0, err 97 | } 98 | end, err := ip2UInt32(strings.Split(ips, "-")[1]) 99 | if err != nil { 100 | return 0, 0, err 101 | } 102 | if start > end { 103 | return 0, 0, errors.New(ips + " error") 104 | } 105 | return start, end, nil 106 | } 107 | 108 | // 192.168.113.0/24 109 | func multipleip3(ips string) (startx uint32, endx uint32, err error) { 110 | host := strings.Split(ips, "/")[0] 111 | mask, err := strconv.Atoi(strings.Split(ips, "/")[1]) 112 | if err != nil { 113 | return 0, 0, errors.New(ips + " " + err.Error() + " ip parse error") 114 | } 115 | if len(strings.Split(host, ".")) != 4 { 116 | return 0, 0, errors.New(ips + " ip parse error") 117 | } 118 | a, err := strconv.Atoi(strings.Split(host, ".")[0]) 119 | b, err := strconv.Atoi(strings.Split(host, ".")[1]) 120 | c, err := strconv.Atoi(strings.Split(host, ".")[2]) 121 | d, err := strconv.Atoi(strings.Split(host, ".")[3]) 122 | if err != nil { 123 | return 0, 0, errors.New(ips + " ip parse error") 124 | } 125 | ipbin := fmt.Sprintf("%08s", strconv.FormatInt(int64(a), 2)) + 126 | fmt.Sprintf("%08s", strconv.FormatInt(int64(b), 2)) + 127 | fmt.Sprintf("%08s", strconv.FormatInt(int64(c), 2)) + 128 | fmt.Sprintf("%08s", strconv.FormatInt(int64(d), 2)) 129 | 130 | start := ipbin[:mask] 131 | end := ipbin[:mask] 132 | for i := 0; i < len(ipbin)-mask; i++ { 133 | start += "0" 134 | end += "1" 135 | } 136 | start1, err := strconv.ParseUint(start, 2, 32) 137 | if err != nil { 138 | return 0, 0, errors.New(ips + " ip parse error: " + err.Error()) 139 | } 140 | end2, err := strconv.ParseUint(end, 2, 32) 141 | if err != nil { 142 | return 0, 0, errors.New(ips + " ip parse error: " + err.Error()) 143 | } 144 | return uint32(start1), uint32(end2), nil 145 | } 146 | 147 | func ip2UInt32(ipnr string) (uint32, error) { 148 | bits := strings.Split(ipnr, ".") 149 | if len(bits) != 4 { 150 | return 0, errors.New("ip2Uint32 error " + ipnr) 151 | } 152 | 153 | b0, err := strconv.Atoi(bits[0]) 154 | if err != nil { 155 | return 0, err 156 | } 157 | b1, err := strconv.Atoi(bits[1]) 158 | if err != nil { 159 | return 0, err 160 | } 161 | b2, err := strconv.Atoi(bits[2]) 162 | if err != nil { 163 | return 0, err 164 | } 165 | b3, err := strconv.Atoi(bits[3]) 166 | if err != nil { 167 | return 0, err 168 | } 169 | 170 | var sum uint32 171 | sum += uint32(b0) << 24 172 | sum += uint32(b1) << 16 173 | sum += uint32(b2) << 8 174 | sum += uint32(b3) 175 | return sum, nil 176 | } 177 | 178 | func UInt32ToIP(intIP uint32) string { 179 | var bytes [4]byte 180 | bytes[0] = byte(intIP & 0xFF) 181 | bytes[1] = byte((intIP >> 8) & 0xFF) 182 | bytes[2] = byte((intIP >> 16) & 0xFF) 183 | bytes[3] = byte((intIP >> 24) & 0xFF) 184 | 185 | return net.IPv4(bytes[3], bytes[2], bytes[1], bytes[0]).String() 186 | } 187 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/lic/lic.go: -------------------------------------------------------------------------------- 1 | package lic 2 | 3 | import ( 4 | "github.com/bufsnake/Monkey/pkg/grdp/core" 5 | "io" 6 | ) 7 | 8 | const ( 9 | LICENSE_REQUEST = 0x01 10 | PLATFORM_CHALLENGE = 0x02 11 | NEW_LICENSE = 0x03 12 | UPGRADE_LICENSE = 0x04 13 | LICENSE_INFO = 0x12 14 | NEW_LICENSE_REQUEST = 0x13 15 | PLATFORM_CHALLENGE_RESPONSE = 0x15 16 | ERROR_ALERT = 0xFF 17 | ) 18 | 19 | // error code 20 | const ( 21 | ERR_INVALID_SERVER_CERTIFICATE = 0x00000001 22 | ERR_NO_LICENSE = 0x00000002 23 | ERR_INVALID_SCOPE = 0x00000004 24 | ERR_NO_LICENSE_SERVER = 0x00000006 25 | STATUS_VALID_CLIENT = 0x00000007 26 | ERR_INVALID_CLIENT = 0x00000008 27 | ERR_INVALID_PRODUCTID = 0x0000000B 28 | ERR_INVALID_MESSAGE_LEN = 0x0000000C 29 | ERR_INVALID_MAC = 0x00000003 30 | ) 31 | 32 | // state transition 33 | const ( 34 | ST_TOTAL_ABORT = 0x00000001 35 | ST_NO_TRANSITION = 0x00000002 36 | ST_RESET_PHASE_TO_START = 0x00000003 37 | ST_RESEND_LAST_MESSAGE = 0x00000004 38 | ) 39 | 40 | /* 41 | """ 42 | @summary: Binary blob data type 43 | @see: http://msdn.microsoft.com/en-us/library/cc240481.aspx 44 | """ 45 | */ 46 | type BinaryBlobType uint16 47 | 48 | const ( 49 | BB_ANY_BLOB = 0x0000 50 | BB_DATA_BLOB = 0x0001 51 | BB_RANDOM_BLOB = 0x0002 52 | BB_CERTIFICATE_BLOB = 0x0003 53 | BB_ERROR_BLOB = 0x0004 54 | BB_ENCRYPTED_DATA_BLOB = 0x0009 55 | BB_KEY_EXCHG_ALG_BLOB = 0x000D 56 | BB_SCOPE_BLOB = 0x000E 57 | BB_CLIENT_USER_NAME_BLOB = 0x000F 58 | BB_CLIENT_MACHINE_NAME_BLOB = 0x0010 59 | ) 60 | 61 | type ErrorMessage struct { 62 | DwErrorCode uint32 63 | DwStateTransaction uint32 64 | Blob []byte 65 | } 66 | 67 | func readErrorMessage(r io.Reader) *ErrorMessage { 68 | m := &ErrorMessage{} 69 | m.DwErrorCode, _ = core.ReadUInt32LE(r) 70 | m.DwStateTransaction, _ = core.ReadUInt32LE(r) 71 | return m 72 | } 73 | 74 | type LicensePacket struct { 75 | BMsgtype uint8 76 | Flag uint8 77 | WMsgSize uint16 78 | LicensingMessage interface{} 79 | } 80 | 81 | func ReadLicensePacket(r io.Reader) *LicensePacket { 82 | l := &LicensePacket{} 83 | l.BMsgtype, _ = core.ReadUInt8(r) 84 | l.Flag, _ = core.ReadUInt8(r) 85 | l.WMsgSize, _ = core.ReadUint16LE(r) 86 | 87 | switch l.BMsgtype { 88 | case ERROR_ALERT: 89 | l.LicensingMessage = readErrorMessage(r) 90 | default: 91 | l.LicensingMessage, _ = core.ReadBytes(int(l.WMsgSize-4), r) 92 | } 93 | 94 | return l 95 | } 96 | 97 | /* 98 | """ 99 | @summary: Blob use by license manager to exchange security data 100 | @see: http://msdn.microsoft.com/en-us/library/cc240481.aspx 101 | """ 102 | */ 103 | type LicenseBinaryBlob struct { 104 | WBlobType uint16 `struc:"little"` 105 | WBlobLen uint16 `struc:"little"` 106 | BlobData []byte `struc:"sizefrom=WBlobLen"` 107 | } 108 | 109 | func NewLicenseBinaryBlob(WBlobType uint16) *LicenseBinaryBlob { 110 | return &LicenseBinaryBlob{} 111 | } 112 | 113 | /* 114 | """ 115 | @summary: License server product information 116 | @see: http://msdn.microsoft.com/en-us/library/cc241915.aspx 117 | """ 118 | */ 119 | type ProductInformation struct { 120 | DwVersion uint32 `struc:"little"` 121 | CbCompanyName uint32 `struc:"little"` 122 | //may contain "Microsoft Corporation" from server microsoft 123 | PbCompanyName []byte `struc:"sizefrom=CbCompanyName"` 124 | CbProductId uint32 `struc:"little"` 125 | //may contain "A02" from microsoft license server 126 | PbProductId []byte `struc:"sizefrom=CbProductId"` 127 | } 128 | 129 | /* 130 | @summary: Send by server to signal license request 131 | 132 | server -> client 133 | 134 | @see: http://msdn.microsoft.com/en-us/library/cc241914.aspx 135 | */ 136 | type ServerLicenseRequest struct { 137 | ServerRandom []byte `struc:"[32]byte"` 138 | ProductInfo ProductInformation `struc:"little"` 139 | KeyExchangeList LicenseBinaryBlob `struc:"little"` 140 | ServerCertificate LicenseBinaryBlob `struc:"little"` 141 | //ScopeList ScopeList 142 | } 143 | 144 | /* 145 | @summary: Send by client to ask new license for client. 146 | RDPY doesn'support license reuse, need it in futur version 147 | @see: http://msdn.microsoft.com/en-us/library/cc241918.aspx 148 | #RSA and must be only RSA 149 | #pure microsoft client ;-) 150 | #http://msdn.microsoft.com/en-us/library/1040af38-c733-4fb3-acd1-8db8cc979eda#id10 151 | */ 152 | 153 | type ClientNewLicenseRequest struct { 154 | PreferredKeyExchangeAlg uint32 `struc:"little"` 155 | PlatformId uint32 `struc:"little"` 156 | ClientRandom []byte `struc:"little"` 157 | EncryptedPreMasterSecret LicenseBinaryBlob `struc:"little"` 158 | ClientUserName LicenseBinaryBlob `struc:"little"` 159 | ClientMachineName LicenseBinaryBlob `struc:"little"` 160 | } 161 | 162 | /* 163 | @summary: challenge send from server to client 164 | @see: http://msdn.microsoft.com/en-us/library/cc241921.aspx 165 | */ 166 | type ServerPlatformChallenge struct { 167 | ConnectFlags uint32 168 | EncryptedPlatformChallenge LicenseBinaryBlob 169 | MACData [16]byte 170 | } 171 | 172 | /* 173 | """ 174 | @summary: client challenge response 175 | @see: http://msdn.microsoft.com/en-us/library/cc241922.aspx 176 | """ 177 | */ 178 | type ClientPLatformChallengeResponse struct { 179 | EncryptedPlatformChallengeResponse LicenseBinaryBlob 180 | EncryptedHWID LicenseBinaryBlob 181 | MACData []byte //[16]byte 182 | } 183 | -------------------------------------------------------------------------------- /pkg/blasting/telnetcli.go: -------------------------------------------------------------------------------- 1 | package blasting 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "net" 7 | "strings" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | type telnetcli struct { 13 | ip string 14 | port string 15 | } 16 | 17 | func (s *telnetcli) Info() string { 18 | return "weak" 19 | } 20 | 21 | func (m *telnetcli) Connect() (string, error) { 22 | usernames := []string{"admin", "root", "guest", "ftp", "www"} 23 | passwords := []string{"R0ck9", "%user%", "%user%123", "%user%1234", "%user%123456", "%user%12345", "%user%@123", "%user%@123456", "%user%@12345", "%user%#123", "%user%#123456", "%user%#12345", "%user%_123", "%user%_123456", "%user%_12345", "%user%123!@#", "%user%!@#$", "%user%!@#", "%user%~!@", "%user%!@#123", "qweasdzxc", "%user%2017", "%user%2016", "%user%2015", "%user%@2017", "%user%@2016", "%user%@2015", "qweasdzxc", "Passw0rd", "admin", "123456", "password", "12345", "1234", "root", "123", "qwerty", "test", "1q2w3e4r", "1qaz2wsx", "qazwsx", "123qwe", "123qaz", "0000", "1234567", "123456qwerty", "password123", "12345678", "1q2w3e", "abc123", "okmnji", "test123", "123456789", "q1w2e3r4", "apache", "qwer1234"} 24 | wait := sync.WaitGroup{} 25 | messages := make(chan message, 600) 26 | fin := make(chan message) 27 | for i := 0; i < 5; i++ { 28 | wait.Add(1) 29 | go m.check(&wait, messages, fin) 30 | } 31 | for _, u := range usernames { 32 | for _, p := range passwords { 33 | messages <- message{ 34 | user: u, 35 | pass: p, 36 | } 37 | } 38 | } 39 | go func() { 40 | close(messages) 41 | wait.Wait() 42 | fin <- message{user: "error"} 43 | }() 44 | select { 45 | case <-time.After(5 * time.Minute): 46 | return "", errors.New("telnet weak password test timeout") 47 | case mess := <-fin: 48 | if mess.user == "error" { 49 | return "", errors.New("telnet weak password test finish,but no password found") 50 | } 51 | return "telnet://" + mess.user + ":" + mess.pass + "@" + m.ip + ":" + m.port, nil 52 | } 53 | } 54 | 55 | func (m *telnetcli) check(wg *sync.WaitGroup, messages chan message, fin chan message) { 56 | defer wg.Done() 57 | for message_ := range messages { 58 | message_.pass = strings.ReplaceAll(message_.pass, "%user%", message_.user) 59 | t := telnet{ 60 | IP: m.ip, 61 | Port: m.port, 62 | IsAuthentication: true, 63 | UserName: message_.user, 64 | Password: message_.pass, 65 | } 66 | telnet_, err := t.Telnet(10) 67 | if err != nil { 68 | log.Println("rdp cli blast error", message_.user, message_.pass, err) 69 | continue 70 | } 71 | if telnet_ { 72 | fin <- message_ 73 | } 74 | } 75 | } 76 | 77 | type telnet struct { 78 | IP string 79 | Port string 80 | IsAuthentication bool 81 | UserName string 82 | Password string 83 | } 84 | 85 | func (this *telnet) Telnet(timeout int) (bool, error) { 86 | raddr := this.IP + ":" + this.Port 87 | conn, err := net.DialTimeout("tcp", raddr, time.Duration(timeout)*time.Second) 88 | if nil != err { 89 | log.Print("pkg: model, func: Telnet, method: net.DialTimeout, errInfo:", err) 90 | return false, err 91 | } 92 | defer conn.Close() 93 | if false == this.telnetProtocolHandshake(conn) { 94 | //log.Print("pkg: model, func: Telnet, method: this.telnetProtocolHandshake, errInfo: telnet protocol handshake failed!!!") 95 | return false, err 96 | } 97 | return true, err 98 | } 99 | 100 | func (this *telnet) telnetProtocolHandshake(conn net.Conn) bool { 101 | var buf [4096]byte 102 | var n int 103 | n, err := conn.Read(buf[0:]) 104 | if nil != err { 105 | log.Print("pkg: model, func: telnetProtocolHandshake1, method: conn.Read, errInfo:", err) 106 | return false 107 | } 108 | 109 | buf[0] = 0xff 110 | buf[1] = 0xfc 111 | buf[2] = 0x25 112 | buf[3] = 0xff 113 | buf[4] = 0xfe 114 | buf[5] = 0x01 115 | n, err = conn.Write(buf[0:6]) 116 | if nil != err { 117 | log.Print("pkg: model, func: telnetProtocolHandshake2, method: conn.Write, errInfo:", err) 118 | return false 119 | } 120 | 121 | n, err = conn.Read(buf[0:]) 122 | if nil != err { 123 | log.Print("pkg: model, func: telnetProtocolHandshake3, method: conn.Read, errInfo:", err) 124 | return false 125 | } 126 | 127 | buf[0] = 0xff 128 | buf[1] = 0xfe 129 | buf[2] = 0x03 130 | buf[3] = 0xff 131 | buf[4] = 0xfc 132 | buf[5] = 0x27 133 | n, err = conn.Write(buf[0:6]) 134 | if nil != err { 135 | log.Print("pkg: model, func: telnetProtocolHandshake4, method: conn.Write, errInfo:", err) 136 | return false 137 | } 138 | 139 | n, err = conn.Read(buf[0:]) 140 | if nil != err { 141 | log.Print("pkg: model, func: telnetProtocolHandshake5, method: conn.Read, errInfo:", err) 142 | return false 143 | } 144 | 145 | //fmt.Println((buf[0:n])) 146 | n, err = conn.Write([]byte(this.UserName + "\r\n")) 147 | if nil != err { 148 | log.Print("pkg: model, func: telnetProtocolHandshake6, method: conn.Write, errInfo:", err) 149 | return false 150 | } 151 | time.Sleep(time.Millisecond * 500) 152 | 153 | n, err = conn.Read(buf[0:]) 154 | if nil != err { 155 | log.Print("pkg: model, func: telnetProtocolHandshake7, method: conn.Read, errInfo:", err) 156 | return false 157 | } 158 | 159 | n, err = conn.Write([]byte(this.Password + "\r\n")) 160 | if nil != err { 161 | log.Print("pkg: model, func: telnetProtocolHandshake8, method: conn.Write, errInfo:", err) 162 | return false 163 | } 164 | time.Sleep(time.Millisecond * 2000) 165 | n, err = conn.Read(buf[0:]) 166 | if nil != err { 167 | log.Print("pkg: model, func: telnetProtocolHandshake9, method: conn.Read, errInfo:", err) 168 | return false 169 | } 170 | if strings.Contains(string(buf[0:n]), "Login Failed") { 171 | return false 172 | } 173 | 174 | buf[0] = 0xff 175 | buf[1] = 0xfc 176 | buf[2] = 0x18 177 | 178 | n, err = conn.Write(buf[0:3]) 179 | if nil != err { 180 | log.Print("pkg: model, func: telnetProtocolHandshake6, method: conn.Write, errInfo:", err) 181 | return false 182 | } 183 | n, err = conn.Read(buf[0:]) 184 | if nil != err { 185 | log.Print("pkg: model, func: telnetProtocolHandshake7, method: conn.Read, errInfo:", err) 186 | return false 187 | } 188 | return true 189 | } 190 | -------------------------------------------------------------------------------- /pkg/grdp/grdp.go: -------------------------------------------------------------------------------- 1 | package grdp 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/bufsnake/Monkey/pkg/grdp/core" 7 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 8 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/nla" 9 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/pdu" 10 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/rfb" 11 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/sec" 12 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/t125" 13 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/tpkt" 14 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/x224" 15 | "log" 16 | "net" 17 | "os" 18 | "sync" 19 | "time" 20 | ) 21 | 22 | const ( 23 | PROTOCOL_RDP = "PROTOCOL_RDP" 24 | PROTOCOL_SSL = "PROTOCOL_SSL" 25 | ) 26 | 27 | type Client struct { 28 | Host string // ip:port 29 | tpkt *tpkt.TPKT 30 | x224 *x224.X224 31 | mcs *t125.MCSClient 32 | sec *sec.Client 33 | pdu *pdu.Client 34 | vnc *rfb.RFB 35 | } 36 | 37 | func NewClient(host string, logLevel glog.LEVEL) *Client { 38 | glog.SetLevel(logLevel) 39 | logger := log.New(os.Stdout, "", 0) 40 | glog.SetLogger(logger) 41 | return &Client{ 42 | Host: host, 43 | } 44 | } 45 | 46 | func (g *Client) loginForSSL(domain, user, pwd string) error { 47 | conn, err := net.DialTimeout("tcp", g.Host, 10*time.Second) 48 | if err != nil { 49 | return fmt.Errorf("[dial err] %v", err) 50 | } 51 | defer conn.Close() 52 | glog.Info(conn.LocalAddr().String()) 53 | 54 | g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd)) 55 | g.x224 = x224.New(g.tpkt) 56 | g.mcs = t125.NewMCSClient(g.x224) 57 | g.sec = sec.NewClient(g.mcs) 58 | g.pdu = pdu.NewClient(g.sec) 59 | 60 | g.sec.SetUser(user) 61 | g.sec.SetPwd(pwd) 62 | g.sec.SetDomain(domain) 63 | 64 | g.tpkt.SetFastPathListener(g.sec) 65 | g.sec.SetFastPathListener(g.pdu) 66 | g.pdu.SetFastPathSender(g.tpkt) 67 | 68 | err = g.x224.Connect() 69 | if err != nil { 70 | return fmt.Errorf("[x224 connect err] %v", err) 71 | } 72 | glog.Info("wait connect ok") 73 | wg := &sync.WaitGroup{} 74 | breakFlag := false 75 | wg.Add(1) 76 | 77 | g.pdu.On("error", func(e error) { 78 | err = e 79 | glog.Error("error", e) 80 | g.pdu.Emit("done") 81 | }) 82 | g.pdu.On("close", func() { 83 | err = errors.New("close") 84 | glog.Info("on close") 85 | g.pdu.Emit("done") 86 | }) 87 | g.pdu.On("success", func() { 88 | err = nil 89 | glog.Info("on success") 90 | g.pdu.Emit("done") 91 | }) 92 | g.pdu.On("ready", func() { 93 | glog.Info("on ready") 94 | g.pdu.Emit("done") 95 | }) 96 | g.pdu.On("update", func(rectangles []pdu.BitmapData) { 97 | glog.Info("on update:", rectangles) 98 | }) 99 | g.pdu.On("done", func() { 100 | if breakFlag == false { 101 | breakFlag = true 102 | wg.Done() 103 | } 104 | }) 105 | wg.Wait() 106 | return err 107 | } 108 | 109 | func (g *Client) loginForRDP(domain, user, pwd string) error { 110 | conn, err := net.DialTimeout("tcp", g.Host, 10*time.Second) 111 | if err != nil { 112 | return fmt.Errorf("[dial err] %v", err) 113 | } 114 | defer conn.Close() 115 | glog.Info(conn.LocalAddr().String()) 116 | 117 | g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd)) 118 | g.x224 = x224.New(g.tpkt) 119 | g.mcs = t125.NewMCSClient(g.x224) 120 | g.sec = sec.NewClient(g.mcs) 121 | g.pdu = pdu.NewClient(g.sec) 122 | 123 | g.sec.SetUser(user) 124 | g.sec.SetPwd(pwd) 125 | g.sec.SetDomain(domain) 126 | 127 | g.tpkt.SetFastPathListener(g.sec) 128 | g.sec.SetFastPathListener(g.pdu) 129 | g.pdu.SetFastPathSender(g.tpkt) 130 | 131 | g.x224.SetRequestedProtocol(x224.PROTOCOL_RDP) 132 | 133 | err = g.x224.Connect() 134 | if err != nil { 135 | return fmt.Errorf("[x224 connect err] %v", err) 136 | } 137 | glog.Info("wait connect ok") 138 | wg := &sync.WaitGroup{} 139 | breakFlag := false 140 | updateCount := 0 141 | wg.Add(1) 142 | 143 | g.pdu.On("error", func(e error) { 144 | err = e 145 | glog.Error("error", e) 146 | g.pdu.Emit("done") 147 | }) 148 | g.pdu.On("close", func() { 149 | err = errors.New("close") 150 | glog.Info("on close") 151 | g.pdu.Emit("done") 152 | }) 153 | g.pdu.On("success", func() { 154 | err = nil 155 | glog.Info("on success") 156 | g.pdu.Emit("done") 157 | }) 158 | g.pdu.On("ready", func() { 159 | glog.Info("on ready") 160 | }) 161 | g.pdu.On("update", func(rectangles []pdu.BitmapData) { 162 | glog.Info("on update:", rectangles) 163 | updateCount += 1 164 | //fmt.Println(updateCount," ",rectangles[0].BitmapLength) 165 | }) 166 | g.pdu.On("done", func() { 167 | if breakFlag == false { 168 | breakFlag = true 169 | wg.Done() 170 | } 171 | }) 172 | 173 | //wait 2 Second 174 | time.Sleep(time.Second * 3) 175 | if breakFlag == false { 176 | breakFlag = true 177 | wg.Done() 178 | } 179 | wg.Wait() 180 | 181 | if updateCount > 100 { 182 | return nil 183 | } 184 | err = errors.New("login failed") 185 | return err 186 | } 187 | 188 | func Login(target, domain, username, password string) error { 189 | var err error 190 | g := NewClient(target, glog.NONE) 191 | //SSL协议登录测试 192 | err = g.loginForSSL(domain, username, password) 193 | if err == nil { 194 | return nil 195 | } 196 | if err.Error() != PROTOCOL_RDP { 197 | return err 198 | } 199 | //RDP协议登录测试 200 | err = g.loginForRDP(domain, username, password) 201 | if err == nil { 202 | return nil 203 | } else { 204 | return err 205 | } 206 | } 207 | 208 | func LoginForSSL(target, domain, username, password string) error { 209 | var err error 210 | g := NewClient(target, glog.NONE) 211 | //SSL协议登录测试 212 | err = g.loginForSSL(domain, username, password) 213 | if err == nil { 214 | return nil 215 | } 216 | return err 217 | } 218 | 219 | func LoginForRDP(target, domain, username, password string) error { 220 | var err error 221 | g := NewClient(target, glog.NONE) 222 | //SSL协议登录测试 223 | err = g.loginForRDP(domain, username, password) 224 | if err == nil { 225 | return nil 226 | } 227 | return err 228 | } 229 | 230 | func VerifyProtocol(target string) string { 231 | var err error 232 | err = LoginForSSL(target, "", "administrator", "test") 233 | if err == nil { 234 | return PROTOCOL_SSL 235 | } 236 | if err.Error() != PROTOCOL_RDP { 237 | return PROTOCOL_RDP 238 | } 239 | return PROTOCOL_SSL 240 | } 241 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/tpkt/tpkt.go: -------------------------------------------------------------------------------- 1 | package tpkt 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "fmt" 7 | "github.com/bufsnake/Monkey/pkg/grdp/core" 8 | "github.com/bufsnake/Monkey/pkg/grdp/emission" 9 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 10 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/nla" 11 | ) 12 | 13 | // take idea from https://github.com/Madnikulin50/gordp 14 | 15 | /** 16 | * Type of tpkt packet 17 | * Fastpath is use to shortcut RDP stack 18 | * @see http://msdn.microsoft.com/en-us/library/cc240621.aspx 19 | * @see http://msdn.microsoft.com/en-us/library/cc240589.aspx 20 | */ 21 | const ( 22 | FASTPATH_ACTION_FASTPATH = 0x0 23 | FASTPATH_ACTION_X224 = 0x3 24 | ) 25 | 26 | /** 27 | * TPKT layer of rdp stack 28 | */ 29 | type TPKT struct { 30 | emission.Emitter 31 | Conn *core.SocketLayer 32 | ntlm *nla.NTLMv2 33 | secFlag byte 34 | lastShortLength int 35 | fastPathListener core.FastPathListener 36 | ntlmSec *nla.NTLMv2Security 37 | } 38 | 39 | func New(s *core.SocketLayer, ntlm *nla.NTLMv2) *TPKT { 40 | t := &TPKT{ 41 | Emitter: *emission.NewEmitter(), 42 | Conn: s, 43 | secFlag: 0, 44 | ntlm: ntlm} 45 | core.StartReadBytes(2, s, t.recvHeader) 46 | return t 47 | } 48 | 49 | func (t *TPKT) StartTLS() error { 50 | return t.Conn.StartTLS() 51 | } 52 | 53 | func (t *TPKT) StartNLA() error { 54 | err := t.StartTLS() 55 | if err != nil { 56 | glog.Info("start tls failed", err) 57 | return err 58 | } 59 | req := nla.EncodeDERTRequest([]nla.Message{t.ntlm.GetNegotiateMessage()}, nil, nil) 60 | _, err = t.Conn.Write(req) 61 | if err != nil { 62 | glog.Info("send NegotiateMessage", err) 63 | return err 64 | } 65 | 66 | resp := make([]byte, 1024) 67 | n, err := t.Conn.Read(resp) 68 | if err != nil { 69 | return fmt.Errorf("read %s", err) 70 | } else { 71 | glog.Debug("StartNLA Read success") 72 | } 73 | return t.recvChallenge(resp[:n]) 74 | } 75 | 76 | func (t *TPKT) recvChallenge(data []byte) error { 77 | glog.Debug("recvChallenge", hex.EncodeToString(data)) 78 | tsreq, err := nla.DecodeDERTRequest(data) 79 | if err != nil { 80 | glog.Info("DecodeDERTRequest", err) 81 | return err 82 | } 83 | glog.Debugf("tsreq:%+v", tsreq) 84 | // get pubkey 85 | pubkey, err := t.Conn.TlsPubKey() 86 | glog.Debugf("pubkey=%+v", pubkey) 87 | 88 | authMsg, ntlmSec := t.ntlm.GetAuthenticateMessage(tsreq.NegoTokens[0].Data) 89 | t.ntlmSec = ntlmSec 90 | 91 | encryptPubkey := ntlmSec.GssEncrypt(pubkey) 92 | req := nla.EncodeDERTRequest([]nla.Message{authMsg}, nil, encryptPubkey) 93 | _, err = t.Conn.Write(req) 94 | if err != nil { 95 | glog.Info("send AuthenticateMessage", err) 96 | return err 97 | } 98 | resp := make([]byte, 1024) 99 | n, err := t.Conn.Read(resp) 100 | if err != nil { 101 | glog.Error("Read:", err) 102 | return fmt.Errorf("read %s", err) 103 | } else { 104 | glog.Debug("recvChallenge Read success") 105 | } 106 | return t.recvPubKeyInc(resp[:n]) 107 | } 108 | 109 | func (t *TPKT) recvPubKeyInc(data []byte) error { 110 | glog.Debug("recvPubKeyInc", hex.EncodeToString(data)) 111 | tsreq, err := nla.DecodeDERTRequest(data) 112 | if err != nil { 113 | glog.Info("DecodeDERTRequest", err) 114 | return err 115 | } 116 | glog.Debug("PubKeyAuth:", tsreq.PubKeyAuth) 117 | //ignore 118 | //pubkey := t.ntlmSec.GssDecrypt([]byte(tsreq.PubKeyAuth)) 119 | domain, username, password := t.ntlm.GetEncodedCredentials() 120 | credentials := nla.EncodeDERTCredentials(domain, username, password) 121 | authInfo := t.ntlmSec.GssEncrypt(credentials) 122 | req := nla.EncodeDERTRequest(nil, authInfo, nil) 123 | _, err = t.Conn.Write(req) 124 | if err != nil { 125 | glog.Info("send AuthenticateMessage", err) 126 | return err 127 | } 128 | 129 | return nil 130 | } 131 | 132 | func (t *TPKT) Read(b []byte) (n int, err error) { 133 | return t.Conn.Read(b) 134 | } 135 | 136 | func (t *TPKT) Write(data []byte) (n int, err error) { 137 | buff := &bytes.Buffer{} 138 | core.WriteUInt8(FASTPATH_ACTION_X224, buff) 139 | core.WriteUInt8(0, buff) 140 | core.WriteUInt16BE(uint16(len(data)+4), buff) 141 | buff.Write(data) 142 | glog.Debug("tpkt Write", hex.EncodeToString(buff.Bytes())) 143 | return t.Conn.Write(buff.Bytes()) 144 | } 145 | 146 | func (t *TPKT) Close() error { 147 | return t.Conn.Close() 148 | } 149 | 150 | func (t *TPKT) SetFastPathListener(f core.FastPathListener) { 151 | t.fastPathListener = f 152 | } 153 | 154 | func (t *TPKT) SendFastPath(secFlag byte, data []byte) (n int, err error) { 155 | buff := &bytes.Buffer{} 156 | core.WriteUInt8(FASTPATH_ACTION_FASTPATH|((secFlag&0x3)<<6), buff) 157 | core.WriteUInt16BE(uint16(len(data)+3)|0x8000, buff) 158 | buff.Write(data) 159 | glog.Debug("TPTK SendFastPath", hex.EncodeToString(buff.Bytes())) 160 | return t.Conn.Write(buff.Bytes()) 161 | } 162 | 163 | func (t *TPKT) recvHeader(s []byte, err error) { 164 | glog.Debug("tpkt recvHeader", hex.EncodeToString(s), err) 165 | if err != nil { 166 | t.Emit("error", err) 167 | return 168 | } 169 | r := bytes.NewReader(s) 170 | version, _ := core.ReadUInt8(r) 171 | if version == FASTPATH_ACTION_X224 { 172 | glog.Debug("tptk recvHeader FASTPATH_ACTION_X224, wait for recvExtendedHeader") 173 | core.StartReadBytes(2, t.Conn, t.recvExtendedHeader) 174 | } else { 175 | t.secFlag = (version >> 6) & 0x3 176 | length, _ := core.ReadUInt8(r) 177 | t.lastShortLength = int(length) 178 | if t.lastShortLength&0x80 != 0 { 179 | core.StartReadBytes(1, t.Conn, t.recvExtendedFastPathHeader) 180 | } else { 181 | core.StartReadBytes(t.lastShortLength-2, t.Conn, t.recvFastPath) 182 | } 183 | } 184 | } 185 | 186 | func (t *TPKT) recvExtendedHeader(s []byte, err error) { 187 | glog.Debug("tpkt recvExtendedHeader", hex.EncodeToString(s), err) 188 | if err != nil { 189 | return 190 | } 191 | r := bytes.NewReader(s) 192 | size, _ := core.ReadUint16BE(r) 193 | glog.Debug("tpkt wait recvData:", size) 194 | core.StartReadBytes(int(size-4), t.Conn, t.recvData) 195 | } 196 | 197 | func (t *TPKT) recvData(s []byte, err error) { 198 | glog.Debug("tpkt recvData", hex.EncodeToString(s), err) 199 | if err != nil { 200 | return 201 | } 202 | t.Emit("data", s) 203 | core.StartReadBytes(2, t.Conn, t.recvHeader) 204 | } 205 | 206 | func (t *TPKT) recvExtendedFastPathHeader(s []byte, err error) { 207 | glog.Debug("tpkt recvExtendedFastPathHeader", hex.EncodeToString(s)) 208 | r := bytes.NewReader(s) 209 | rightPart, err := core.ReadUInt8(r) 210 | if err != nil { 211 | glog.Error("TPTK recvExtendedFastPathHeader", err) 212 | return 213 | } 214 | 215 | leftPart := t.lastShortLength & ^0x80 216 | packetSize := (leftPart << 8) + int(rightPart) 217 | core.StartReadBytes(packetSize-3, t.Conn, t.recvFastPath) 218 | } 219 | 220 | func (t *TPKT) recvFastPath(s []byte, err error) { 221 | glog.Debug("tpkt recvFastPath") 222 | if err != nil { 223 | return 224 | } 225 | 226 | t.fastPathListener.RecvFastPath(t.secFlag, s) 227 | core.StartReadBytes(2, t.Conn, t.recvHeader) 228 | } 229 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/x224/x224.go: -------------------------------------------------------------------------------- 1 | package x224 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "errors" 7 | "fmt" 8 | "github.com/bufsnake/Monkey/pkg/grdp/core" 9 | "github.com/bufsnake/Monkey/pkg/grdp/emission" 10 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 11 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/tpkt" 12 | 13 | "github.com/lunixbochs/struc" 14 | ) 15 | 16 | // take idea from https://github.com/Madnikulin50/gordp 17 | 18 | /** 19 | * Message type present in X224 packet header 20 | */ 21 | type MessageType byte 22 | 23 | const ( 24 | TPDU_CONNECTION_REQUEST MessageType = 0xE0 25 | TPDU_CONNECTION_CONFIRM = 0xD0 26 | TPDU_DISCONNECT_REQUEST = 0x80 27 | TPDU_DATA = 0xF0 28 | TPDU_ERROR = 0x70 29 | ) 30 | 31 | /** 32 | * Type of negotiation present in negotiation packet 33 | */ 34 | type NegotiationType byte 35 | 36 | const ( 37 | TYPE_RDP_NEG_REQ NegotiationType = 0x01 38 | TYPE_RDP_NEG_RSP = 0x02 39 | TYPE_RDP_NEG_FAILURE = 0x03 40 | ) 41 | 42 | /** 43 | * Protocols available for x224 layer 44 | */ 45 | 46 | const ( 47 | PROTOCOL_RDP uint32 = 0x00000000 48 | PROTOCOL_SSL = 0x00000001 49 | PROTOCOL_HYBRID = 0x00000002 50 | PROTOCOL_HYBRID_EX = 0x00000008 51 | ) 52 | 53 | /** 54 | * Use to negotiate security layer of RDP stack 55 | * In node-rdpjs only ssl is available 56 | * @param opt {object} component type options 57 | * @see request -> http://msdn.microsoft.com/en-us/library/cc240500.aspx 58 | * @see response -> http://msdn.microsoft.com/en-us/library/cc240506.aspx 59 | * @see failure ->http://msdn.microsoft.com/en-us/library/cc240507.aspx 60 | */ 61 | type Negotiation struct { 62 | Type NegotiationType `struc:"byte"` 63 | Flag uint8 `struc:"uint8"` 64 | Length uint16 `struc:"little"` 65 | Result uint32 `struc:"little"` 66 | } 67 | 68 | func NewNegotiation() *Negotiation { 69 | return &Negotiation{0, 0, 0x0008 /*constant*/, PROTOCOL_RDP} 70 | } 71 | 72 | /** 73 | * X224 client connection request 74 | * @param opt {object} component type options 75 | * @see http://msdn.microsoft.com/en-us/library/cc240470.aspx 76 | */ 77 | type ClientConnectionRequestPDU struct { 78 | Len uint8 79 | Code MessageType 80 | Padding1 uint16 81 | Padding2 uint16 82 | Padding3 uint8 83 | Cookie []byte 84 | ProtocolNeg *Negotiation 85 | } 86 | 87 | func NewClientConnectionRequestPDU(coockie []byte) *ClientConnectionRequestPDU { 88 | x := ClientConnectionRequestPDU{0, TPDU_CONNECTION_REQUEST, 0, 0, 0, 89 | coockie, NewNegotiation()} 90 | x.Len = uint8(len(x.Serialize()) - 1) 91 | return &x 92 | } 93 | 94 | func (x *ClientConnectionRequestPDU) Serialize() []byte { 95 | buff := &bytes.Buffer{} 96 | core.WriteUInt8(x.Len, buff) 97 | core.WriteUInt8(uint8(x.Code), buff) 98 | core.WriteUInt16BE(x.Padding1, buff) 99 | core.WriteUInt16BE(x.Padding2, buff) 100 | core.WriteUInt8(x.Padding3, buff) 101 | 102 | buff.Write(x.Cookie) 103 | if x.Len > 14 { 104 | core.WriteUInt16LE(0x0A0D, buff) 105 | } 106 | struc.Pack(buff, x.ProtocolNeg) 107 | return buff.Bytes() 108 | } 109 | 110 | /** 111 | * X224 Server connection confirm 112 | * @param opt {object} component type options 113 | * @see http://msdn.microsoft.com/en-us/library/cc240506.aspx 114 | */ 115 | type ServerConnectionConfirm struct { 116 | Len uint8 117 | Code MessageType 118 | Padding1 uint16 119 | Padding2 uint16 120 | Padding3 uint8 121 | ProtocolNeg *Negotiation 122 | } 123 | 124 | /** 125 | * Header of each data message from x224 layer 126 | * @returns {type.Component} 127 | */ 128 | type DataHeader struct { 129 | Header uint8 `struc:"little"` 130 | MessageType MessageType `struc:"uint8"` 131 | Separator uint8 `struc:"little"` 132 | } 133 | 134 | func NewDataHeader() *DataHeader { 135 | return &DataHeader{2, TPDU_DATA /* constant */, 0x80 /*constant*/} 136 | } 137 | 138 | /** 139 | * Common X224 Automata 140 | * @param presentation {Layer} presentation layer 141 | */ 142 | type X224 struct { 143 | emission.Emitter 144 | transport core.Transport 145 | requestedProtocol uint32 146 | selectedProtocol uint32 147 | dataHeader *DataHeader 148 | } 149 | 150 | func New(t core.Transport) *X224 { 151 | x := &X224{ 152 | *emission.NewEmitter(), 153 | t, 154 | PROTOCOL_RDP | PROTOCOL_SSL | PROTOCOL_HYBRID, 155 | PROTOCOL_SSL, 156 | NewDataHeader(), 157 | } 158 | 159 | t.On("close", func() { 160 | x.Emit("close") 161 | }).On("error", func(err error) { 162 | x.Emit("error", err) 163 | }) 164 | 165 | return x 166 | } 167 | 168 | func (x *X224) Read(b []byte) (n int, err error) { 169 | return x.transport.Read(b) 170 | } 171 | 172 | func (x *X224) Write(b []byte) (n int, err error) { 173 | buff := &bytes.Buffer{} 174 | err = struc.Pack(buff, x.dataHeader) 175 | if err != nil { 176 | return 0, err 177 | } 178 | buff.Write(b) 179 | 180 | glog.Debug("x224 write:", hex.EncodeToString(buff.Bytes())) 181 | return x.transport.Write(buff.Bytes()) 182 | } 183 | 184 | func (x *X224) Close() error { 185 | return x.transport.Close() 186 | } 187 | 188 | func (x *X224) SetRequestedProtocol(p uint32) { 189 | x.requestedProtocol = p 190 | } 191 | 192 | func (x *X224) Connect() error { 193 | if x.transport == nil { 194 | return errors.New("no transport") 195 | } 196 | message := NewClientConnectionRequestPDU(make([]byte, 0)) 197 | message.ProtocolNeg.Type = TYPE_RDP_NEG_REQ 198 | message.ProtocolNeg.Result = uint32(x.requestedProtocol) 199 | 200 | glog.Debug("x224 sendConnectionRequest", hex.EncodeToString(message.Serialize())) 201 | _, err := x.transport.Write(message.Serialize()) 202 | x.transport.Once("data", x.recvConnectionConfirm) 203 | return err 204 | } 205 | 206 | func (x *X224) recvConnectionConfirm(s []byte) { 207 | glog.Debug("x224 recvConnectionConfirm ", hex.EncodeToString(s)) 208 | message := &ServerConnectionConfirm{} 209 | if err := struc.Unpack(bytes.NewReader(s), message); err != nil { 210 | glog.Error("ReadServerConnectionConfirm err", err) 211 | return 212 | } 213 | glog.Debugf("message: %+v", *message.ProtocolNeg) 214 | if message.ProtocolNeg.Type == TYPE_RDP_NEG_FAILURE { 215 | glog.Error(fmt.Sprintf("NODE_RDP_PROTOCOL_X224_NEG_FAILURE with code: %d,see https://msdn.microsoft.com/en-us/library/cc240507.aspx", 216 | message.ProtocolNeg.Result)) 217 | //only use Standard RDP Security mechanisms 218 | if message.ProtocolNeg.Result == 2 { 219 | glog.Info("Only use Standard RDP Security mechanisms, Reconnect with Standard RDP") 220 | x.Emit("error", errors.New("PROTOCOL_RDP")) 221 | } 222 | x.Close() 223 | return 224 | } 225 | 226 | if message.ProtocolNeg.Type == TYPE_RDP_NEG_RSP { 227 | glog.Info("TYPE_RDP_NEG_RSP") 228 | x.selectedProtocol = message.ProtocolNeg.Result 229 | } 230 | 231 | if x.selectedProtocol == PROTOCOL_HYBRID_EX { 232 | glog.Error("NODE_RDP_PROTOCOL_HYBRID_EX_NOT_SUPPORTED") 233 | return 234 | } 235 | 236 | x.transport.On("data", x.recvData) 237 | 238 | if x.selectedProtocol == PROTOCOL_RDP { 239 | glog.Info("*** RDP security selected ***") 240 | x.Emit("connect", x.selectedProtocol) 241 | return 242 | } 243 | 244 | if x.selectedProtocol == PROTOCOL_SSL { 245 | glog.Info("*** SSL security selected ***") 246 | err := x.transport.(*tpkt.TPKT).StartTLS() 247 | if err != nil { 248 | glog.Error("start tls failed:", err) 249 | return 250 | } 251 | x.Emit("connect", x.selectedProtocol) 252 | return 253 | } 254 | 255 | if x.selectedProtocol == PROTOCOL_HYBRID { 256 | glog.Info("*** NLA Security selected ***") 257 | err := x.transport.(*tpkt.TPKT).StartNLA() 258 | if err != nil { 259 | glog.Error("start NLA failed:", err) 260 | return 261 | } 262 | x.Emit("connect", x.selectedProtocol) 263 | return 264 | } 265 | } 266 | 267 | func (x *X224) recvData(s []byte) { 268 | glog.Debug("x224 recvData", hex.EncodeToString(s), "emit data") 269 | // x224 header takes 3 bytes 270 | x.Emit("data", s[3:]) 271 | } 272 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= 2 | github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= 3 | github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= 4 | github.com/Ullaakut/nmap v1.0.0 h1://XvtkKnrTtEt3E5xzAAtwfvqRoJON/aolr0Larm9eQ= 5 | github.com/Ullaakut/nmap v1.0.0/go.mod h1:fkC066hwfcoKwlI7DS2ARTggSVtBTZYCjVH1TzuTMaQ= 6 | github.com/bufsnake/go-masscan v0.0.0-20210111015631-180a4e32f7bf h1:9sWYmL/GU1eCneoOzlBORJwF8BwDdBcFFUj1pPTN0xY= 7 | github.com/bufsnake/go-masscan v0.0.0-20210111015631-180a4e32f7bf/go.mod h1:z90vXB8E10LNDzw8QbcbrToDxD/bs5I+GfRjZZOYvnU= 8 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 10 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= 12 | github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= 13 | github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= 14 | github.com/garyburd/redigo v1.6.3 h1:HCeeRluvAgMusMomi1+6Y5dmFOdYV/JzoRrrbFlkGIc= 15 | github.com/garyburd/redigo v1.6.3/go.mod h1:rTb6epsqigu3kYKBnaF028A7Tf/Aw5s0cqA47doKKqw= 16 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= 17 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= 18 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= 19 | github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= 20 | github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 21 | github.com/gosnmp/gosnmp v1.34.0 h1:p96iiNTTdL4ZYspPC3leSKXiHfE1NiIYffMu9100p5E= 22 | github.com/gosnmp/gosnmp v1.34.0/go.mod h1:QWTRprXN9haHFof3P96XTDYc46boCGAh5IXp0DniEx4= 23 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= 24 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 25 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 26 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 27 | github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358 h1:hVXNJ57IHkOA8FBq80UG263MEBwNUMfS9c82J2QE5UQ= 28 | github.com/huin/asn1ber v0.0.0-20120622192748-af09f62e6358/go.mod h1:qBE210J2T9uLXRB3GNc73SvZACDEFAmDCOlDkV47zbY= 29 | github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5 h1:ZcsPFW8UgACapqjcrBJx0PuyT4ppArO5VFn0vgnkvmc= 30 | github.com/icodeface/tls v0.0.0-20190904083142-17aec93c60e5/go.mod h1:VJNHW2GxCtQP/IQtXykBIPBV8maPJ/dHWirVTwm9GwY= 31 | github.com/jlaffaye/ftp v0.0.0-20220310202011-d2c44e311e78 h1:urWv38lDLjDRk5fG9P8vvxlfpQXaKtRlZc+QLKk3FRA= 32 | github.com/jlaffaye/ftp v0.0.0-20220310202011-d2c44e311e78/go.mod h1:oZaomI+9/et52UBjvNU9LCIqmgt816+7ljXCx0EIPzo= 33 | github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ= 34 | github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= 35 | github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= 36 | github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= 37 | github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= 38 | github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= 39 | github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= 40 | github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= 41 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 42 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 43 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 44 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 45 | github.com/sijms/go-ora/v2 v2.4.16 h1:D3zfW8XWWKrIf0JRMOzHPuZyJX3hidpZ3W7xQLDTm5c= 46 | github.com/sijms/go-ora/v2 v2.4.16/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk= 47 | github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8 h1:GVFkBBJAEO3CpzIYcDDBdpUObzKwVW9okNWcLYL/nnU= 48 | github.com/stacktitan/smb v0.0.0-20190531122847-da9a425dceb8/go.mod h1:phLSETqH/UJsBtwDVBxSfJKwwkbJcGyy2Q/h4k+bmww= 49 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 50 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 51 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 52 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 53 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 54 | github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= 55 | github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= 56 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 57 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 58 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 59 | golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= 60 | golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 61 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 62 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 63 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 64 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 65 | golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 66 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 67 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 68 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 69 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 70 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 71 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 72 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 73 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 74 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 75 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= 76 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 77 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= 78 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 79 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 80 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 81 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 82 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 83 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 84 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 85 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 86 | golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 87 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 88 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 89 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 90 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 91 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 92 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= 93 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 94 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 95 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 96 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 97 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 98 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 99 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 100 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/pdu/cliprdr.go: -------------------------------------------------------------------------------- 1 | package pdu 2 | 3 | import ( 4 | "bytes" 5 | "github.com/bufsnake/Monkey/pkg/grdp/core" 6 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 7 | ) 8 | 9 | /** 10 | * Initialization Sequence\n 11 | * Client Server\n 12 | * | |\n 13 | * |<----------------------Server Clipboard Capabilities PDU-----------------|\n 14 | * |<-----------------------------Monitor Ready PDU--------------------------|\n 15 | * |-----------------------Client Clipboard Capabilities PDU---------------->|\n 16 | * |---------------------------Temporary Directory PDU---------------------->|\n 17 | * |-------------------------------Format List PDU-------------------------->|\n 18 | * |<--------------------------Format List Response PDU----------------------|\n 19 | * 20 | */ 21 | 22 | /** 23 | * Data Transfer Sequences\n 24 | * Shared Local\n 25 | * Clipboard Owner Clipboard Owner\n 26 | * | |\n 27 | * |-------------------------------------------------------------------------|\n _ 28 | * |-------------------------------Format List PDU-------------------------->|\n | 29 | * |<--------------------------Format List Response PDU----------------------|\n _| Copy 30 | * Sequence 31 | * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n 32 | * |-------------------------------------------------------------------------|\n 33 | * |-------------------------------------------------------------------------|\n _ 34 | * |<--------------------------Format Data Request PDU-----------------------|\n | Paste 35 | * Sequence Palette, 36 | * |---------------------------Format Data Response PDU--------------------->|\n _| Metafile, 37 | * File List Data 38 | * |-------------------------------------------------------------------------|\n 39 | * |-------------------------------------------------------------------------|\n _ 40 | * |<------------------------Format Contents Request PDU---------------------|\n | Paste 41 | * Sequence 42 | * |-------------------------Format Contents Response PDU------------------->|\n _| File 43 | * Stream Data 44 | * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n 45 | * |-------------------------------------------------------------------------|\n 46 | * 47 | */ 48 | 49 | type MsgType uint16 50 | 51 | const ( 52 | CB_MONITOR_READY = 0x0001 53 | CB_FORMAT_LIST = 0x0002 54 | CB_FORMAT_LIST_RESPONSE = 0x0003 55 | CB_FORMAT_DATA_REQUEST = 0x0004 56 | CB_FORMAT_DATA_RESPONSE = 0x0005 57 | CB_TEMP_DIRECTORY = 0x0006 58 | CB_CLIP_CAPS = 0x0007 59 | CB_FILECONTENTS_REQUEST = 0x0008 60 | CB_FILECONTENTS_RESPONSE = 0x0009 61 | CB_LOCK_CLIPDATA = 0x000A 62 | CB_UNLOCK_CLIPDATA = 0x000B 63 | ) 64 | 65 | type MsgFlags uint16 66 | 67 | const ( 68 | CB_RESPONSE_OK = 0x0001 69 | CB_RESPONSE_FAIL = 0x0002 70 | CB_ASCII_NAMES = 0x0004 71 | ) 72 | 73 | type DwFlags uint32 74 | 75 | const ( 76 | FILECONTENTS_SIZE = 0x00000001 77 | FILECONTENTS_RANGE = 0x00000002 78 | ) 79 | 80 | type CliprdrPDUHeader struct { 81 | MsgType uint16 `struc:"little"` 82 | MsgFlags uint16 `struc:"little"` 83 | DataLen uint32 `struc:"little"` 84 | } 85 | 86 | func NewCliprdrPDUHeader(mType, flags uint16, ln uint32) *CliprdrPDUHeader { 87 | return &CliprdrPDUHeader{ 88 | MsgType: mType, 89 | MsgFlags: flags, 90 | DataLen: ln, 91 | } 92 | } 93 | 94 | /* 95 | func (c *CliprdrPDU) serialize() []byte { 96 | b := &bytes.Buffer{} 97 | 98 | return b.Bytes() 99 | } 100 | 101 | func (c *CliprdrPDU) SendCliprdrGeneralCapability() { 102 | 103 | } 104 | func (c *CliprdrPDU) RecvCliprdrCaps() { 105 | 106 | } 107 | 108 | func (c *CliprdrPDU) RecvMonitorReady() { 109 | 110 | } 111 | 112 | func (c *CliprdrPDU) SendCliprdrFileContentsRequest() { 113 | 114 | } 115 | func (c *CliprdrPDU) SendCliprdrFileContentsResponse() { 116 | 117 | } 118 | func (c *CliprdrPDU) SendCliprdrClientFormatList() { 119 | 120 | } 121 | 122 | func (c *CliprdrPDU) RecvCliprdrClientFormatListResponse() { 123 | 124 | } 125 | */ 126 | type CliprdrClient struct { 127 | useLongFormatNames bool 128 | streamFileClipEnabled bool 129 | fileClipNoFilePaths bool 130 | canLockClipData bool 131 | hasHugeFileSupport bool 132 | } 133 | 134 | func process_message(s []byte) { 135 | r := bytes.NewReader(s) 136 | 137 | msgType, _ := core.ReadUint16LE(r) 138 | flag, _ := core.ReadUint16LE(r) 139 | length, _ := core.ReadUInt32LE(r) 140 | 141 | glog.Debug("cliprdr: type=%d flag=%d length=%d", msgType, flag, length) 142 | 143 | switch msgType { 144 | case CB_MONITOR_READY: 145 | //clipboard_sync(plugin->device_data); 146 | break 147 | case CB_FORMAT_LIST: 148 | //clipboard_format_list(plugin->device_data, flag, 149 | // data + 8, length); 150 | //cliprdr_send_packet(plugin, CB_FORMAT_LIST_RESPONSE, 151 | // CB_RESPONSE_OK, NULL, 0); 152 | break 153 | case CB_FORMAT_LIST_RESPONSE: 154 | //clipboard_format_list_response(plugin->device_data, flag); 155 | break 156 | case CB_FORMAT_DATA_REQUEST: 157 | //format = GET_UINT32(data, 8); 158 | //clipboard_request_data(plugin->device_data, format); 159 | break 160 | case CB_FORMAT_DATA_RESPONSE: 161 | //clipboard_handle_data(plugin->device_data, flag, 162 | //data + 8, length); 163 | //break; 164 | case CB_CLIP_CAPS: 165 | //clipboard_handle_caps(plugin->device_data, flag, 166 | //data + 8, length); 167 | break 168 | default: 169 | glog.Error("type %d not supported", msgType) 170 | break 171 | } 172 | 173 | } 174 | 175 | type CliprdrGeneralCapabilitySet struct { 176 | CapabilitySetType uint16 `struc:"little"` 177 | CapabilitySetLength uint16 `struc:"little"` 178 | Version uint32 `struc:"little"` 179 | GeneralFlags uint32 `struc:"little"` 180 | } 181 | type CliprdrCapabilitySets struct { 182 | CapabilitySetType uint16 `struc:"little"` 183 | LengthCapability uint16 `struc:"little,sizeof=CapabilityData"` 184 | CapabilityData []byte `struc:"little"` 185 | } 186 | type CliprdrCapabilitiesPDU struct { 187 | *CliprdrPDUHeader `struc:"little"` 188 | CCapabilitiesSets uint16 `struc:"little"` 189 | Pad1 uint16 `struc:"little"` 190 | CapabilitySets CliprdrGeneralCapabilitySet `struc:"little"` 191 | } 192 | 193 | type CliprdrMonitorReady struct { 194 | *CliprdrPDUHeader `struc:"little"` 195 | } 196 | 197 | type GeneralFlags uint32 198 | 199 | const ( 200 | /* CLIPRDR_GENERAL_CAPABILITY.generalFlags */ 201 | CB_USE_LONG_FORMAT_NAMES = 0x00000002 202 | CB_STREAM_FILECLIP_ENABLED = 0x00000004 203 | CB_FILECLIP_NO_FILE_PATHS = 0x00000008 204 | CB_CAN_LOCK_CLIPDATA = 0x00000010 205 | CB_HUGE_FILE_SUPPORT_ENABLED = 0x00000020 206 | ) 207 | 208 | const ( 209 | /* CLIPRDR_GENERAL_CAPABILITY.version */ 210 | CB_CAPS_VERSION_1 = 0x00000001 211 | CB_CAPS_VERSION_2 = 0x00000002 212 | ) 213 | const ( 214 | CB_CAPSTYPE_GENERAL_LEN = 12 215 | ) 216 | 217 | func CliprdrInit(context CliprdrClient) { 218 | var ( 219 | generalFlags uint32 220 | generalCapabilitySet CliprdrGeneralCapabilitySet 221 | monitorReady CliprdrMonitorReady 222 | capabilities CliprdrCapabilitiesPDU 223 | ) 224 | 225 | generalFlags = 0 226 | monitorReady.MsgType = CB_MONITOR_READY 227 | capabilities.MsgType = CB_CLIP_CAPS 228 | 229 | if context.useLongFormatNames { 230 | generalFlags |= CB_USE_LONG_FORMAT_NAMES 231 | } 232 | 233 | if context.streamFileClipEnabled { 234 | generalFlags |= CB_STREAM_FILECLIP_ENABLED 235 | } 236 | 237 | if context.fileClipNoFilePaths { 238 | generalFlags |= CB_FILECLIP_NO_FILE_PATHS 239 | } 240 | 241 | if context.canLockClipData { 242 | generalFlags |= CB_CAN_LOCK_CLIPDATA 243 | } 244 | 245 | if context.hasHugeFileSupport { 246 | generalFlags |= CB_HUGE_FILE_SUPPORT_ENABLED 247 | } 248 | 249 | capabilities.MsgType = CB_CLIP_CAPS 250 | capabilities.MsgFlags = 0 251 | capabilities.DataLen = 4 + CB_CAPSTYPE_GENERAL_LEN 252 | capabilities.CCapabilitiesSets = 1 253 | 254 | generalCapabilitySet.CapabilitySetType = 0x0001 255 | generalCapabilitySet.CapabilitySetLength = CB_CAPSTYPE_GENERAL_LEN 256 | generalCapabilitySet.Version = CB_CAPS_VERSION_2 257 | generalCapabilitySet.GeneralFlags = generalFlags 258 | capabilities.CapabilitySets = generalCapabilitySet 259 | 260 | /* if ((err= context->ServerCapabilities(context, &capabilities))){ 261 | //glog.Error(TAG, "ServerCapabilities failed with error %" PRIu32 "!", err); 262 | return err 263 | } 264 | 265 | if ((err = context->MonitorReady(context, &monitorReady))){ 266 | //glog.Error("MonitorReady failed with error %" PRIu32 "!", err); 267 | return err 268 | }*/ 269 | 270 | //return err 271 | } 272 | 273 | // temp dir 274 | type CliprdrTempDirectory struct { 275 | Header *CliprdrPDUHeader 276 | SzTempDir string 277 | } 278 | 279 | // format list 280 | type CliprdrFormat struct { 281 | FormatId uint32 282 | FormatName string 283 | } 284 | type CliprdrFormatList struct { 285 | Header *CliprdrPDUHeader 286 | NumFormats uint32 287 | Formats []CliprdrFormat 288 | } 289 | type ClipboardFormats uint16 290 | 291 | const ( 292 | CB_FORMAT_HTML = 0xD010 293 | CB_FORMAT_PNG = 0xD011 294 | CB_FORMAT_JPEG = 0xD012 295 | CB_FORMAT_GIF = 0xD013 296 | CB_FORMAT_TEXTURILIST = 0xD014 297 | CB_FORMAT_GNOMECOPIEDFILES = 0xD015 298 | CB_FORMAT_MATECOPIEDFILES = 0xD016 299 | ) 300 | 301 | // lock or unlock 302 | type CliprdrCtrlClipboardData struct { 303 | Header *CliprdrPDUHeader 304 | ClipDataId uint32 305 | } 306 | 307 | // format data 308 | type CliprdrFormatDataRequest struct { 309 | Header *CliprdrPDUHeader 310 | RequestedFormatId uint32 311 | } 312 | type CliprdrFormatDataResponse struct { 313 | Header *CliprdrPDUHeader 314 | RequestedFormatData []byte 315 | } 316 | 317 | // file contents 318 | type CliprdrFileContentsRequest struct { 319 | Header *CliprdrPDUHeader 320 | StreamId uint32 321 | Lindex int32 322 | DwFlags uint32 323 | NPositionLow uint32 324 | NPositionHigh uint32 325 | CbRequested uint32 326 | ClipDataId uint32 327 | } 328 | 329 | func NewCliprdrFileContentsRequest() *CliprdrFileContentsRequest { 330 | return &CliprdrFileContentsRequest{ 331 | Header: NewCliprdrPDUHeader(CB_FILECONTENTS_REQUEST, 0, 0), 332 | } 333 | } 334 | 335 | type CliprdrFileContentsResponse struct { 336 | Header *CliprdrPDUHeader 337 | StreamId uint32 338 | CbRequested uint32 339 | RequestedData []byte 340 | } 341 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/pdu/pdu.go: -------------------------------------------------------------------------------- 1 | package pdu 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "github.com/bufsnake/Monkey/pkg/grdp/core" 7 | "github.com/bufsnake/Monkey/pkg/grdp/emission" 8 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 9 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/t125/gcc" 10 | ) 11 | 12 | type PDULayer struct { 13 | emission.Emitter 14 | transport core.Transport 15 | sharedId uint32 16 | userId uint16 17 | channelId uint16 18 | serverCapabilities map[CapsType]Capability 19 | clientCapabilities map[CapsType]Capability 20 | fastPathSender core.FastPathSender 21 | demandActivePDU *DemandActivePDU 22 | } 23 | 24 | func NewPDULayer(t core.Transport) *PDULayer { 25 | p := &PDULayer{ 26 | Emitter: *emission.NewEmitter(), 27 | transport: t, 28 | sharedId: 0x103EA, 29 | serverCapabilities: map[CapsType]Capability{ 30 | CAPSTYPE_GENERAL: &GeneralCapability{ 31 | ProtocolVersion: 0x0200, 32 | }, 33 | CAPSTYPE_BITMAP: &BitmapCapability{ 34 | Receive1BitPerPixel: 0x0001, 35 | Receive4BitsPerPixel: 0x0001, 36 | Receive8BitsPerPixel: 0x0001, 37 | BitmapCompressionFlag: 0x0001, 38 | MultipleRectangleSupport: 0x0001, 39 | }, 40 | CAPSTYPE_ORDER: &OrderCapability{ 41 | DesktopSaveXGranularity: 1, 42 | DesktopSaveYGranularity: 20, 43 | MaximumOrderLevel: 1, 44 | OrderFlags: NEGOTIATEORDERSUPPORT, 45 | DesktopSaveSize: 480 * 480, 46 | }, 47 | CAPSTYPE_POINTER: &PointerCapability{ColorPointerCacheSize: 20}, 48 | CAPSTYPE_INPUT: &InputCapability{}, 49 | CAPSTYPE_VIRTUALCHANNEL: &VirtualChannelCapability{}, 50 | CAPSTYPE_FONT: &FontCapability{SupportFlags: 0x0001}, 51 | CAPSTYPE_COLORCACHE: &ColorCacheCapability{CacheSize: 0x0006}, 52 | CAPSTYPE_SHARE: &ShareCapability{}, 53 | }, 54 | clientCapabilities: map[CapsType]Capability{ 55 | CAPSTYPE_GENERAL: &GeneralCapability{ 56 | ProtocolVersion: 0x0200, 57 | }, 58 | CAPSTYPE_BITMAP: &BitmapCapability{ 59 | Receive1BitPerPixel: 0x0001, 60 | Receive4BitsPerPixel: 0x0001, 61 | Receive8BitsPerPixel: 0x0001, 62 | BitmapCompressionFlag: 0x0001, 63 | MultipleRectangleSupport: 0x0001, 64 | }, 65 | CAPSTYPE_ORDER: &OrderCapability{ 66 | DesktopSaveXGranularity: 1, 67 | DesktopSaveYGranularity: 20, 68 | MaximumOrderLevel: 1, 69 | OrderFlags: NEGOTIATEORDERSUPPORT, 70 | DesktopSaveSize: 480 * 480, 71 | }, 72 | CAPSTYPE_BITMAPCACHE: &BitmapCacheCapability{}, 73 | CAPSTYPE_POINTER: &PointerCapability{ColorPointerCacheSize: 20}, 74 | CAPSTYPE_INPUT: &InputCapability{}, 75 | CAPSTYPE_BRUSH: &BrushCapability{}, 76 | CAPSTYPE_GLYPHCACHE: &GlyphCapability{}, 77 | CAPSTYPE_OFFSCREENCACHE: &OffscreenBitmapCacheCapability{}, 78 | CAPSTYPE_VIRTUALCHANNEL: &VirtualChannelCapability{}, 79 | CAPSTYPE_SOUND: &SoundCapability{}, 80 | CAPSETTYPE_MULTIFRAGMENTUPDATE: &MultiFragmentUpdate{}, 81 | CAPSTYPE_RAIL: &RemoteProgramsCapability{ 82 | RailSupportLevel: RAIL_LEVEL_SUPPORTED | 83 | RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | 84 | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED | 85 | RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED | 86 | RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | 87 | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED | 88 | RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED | 89 | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED, 90 | }, 91 | }, 92 | } 93 | 94 | t.On("close", func() { 95 | p.Emit("close") 96 | }).On("error", func(err error) { 97 | p.Emit("error", err) 98 | }) 99 | return p 100 | } 101 | 102 | func (p *PDULayer) sendPDU(message PDUMessage) { 103 | pdu := NewPDU(p.userId, message) 104 | p.transport.Write(pdu.serialize()) 105 | } 106 | 107 | func (p *PDULayer) sendDataPDU(message DataPDUData) { 108 | dataPdu := NewDataPDU(message, p.sharedId) 109 | p.sendPDU(dataPdu) 110 | } 111 | 112 | func (p *PDULayer) SetFastPathSender(f core.FastPathSender) { 113 | p.fastPathSender = f 114 | } 115 | 116 | type Client struct { 117 | *PDULayer 118 | clientCoreData *gcc.ClientCoreData 119 | remoteAppMode bool 120 | enableCliprdr bool 121 | } 122 | 123 | func NewClient(t core.Transport) *Client { 124 | c := &Client{ 125 | PDULayer: NewPDULayer(t), 126 | } 127 | c.transport.Once("connect", c.connect) 128 | return c 129 | } 130 | 131 | func (c *Client) connect(data *gcc.ClientCoreData, userId uint16, channelId uint16) { 132 | glog.Debug("pdu connect:", userId, ",", channelId) 133 | c.clientCoreData = data 134 | c.userId = userId 135 | c.channelId = channelId 136 | c.transport.Once("data", c.recvDemandActivePDU) 137 | } 138 | 139 | func (c *Client) recvDemandActivePDU(s []byte) { 140 | glog.Debug("PDU recvDemandActivePDU", hex.EncodeToString(s)) 141 | r := bytes.NewReader(s) 142 | pdu, err := readPDU(r) 143 | if err != nil { 144 | glog.Error(err) 145 | return 146 | } 147 | if pdu.ShareCtrlHeader.PDUType != PDUTYPE_DEMANDACTIVEPDU { 148 | glog.Info("PDU ignore message during connection sequence, type is", pdu.ShareCtrlHeader.PDUType) 149 | c.transport.Once("data", c.recvDemandActivePDU) 150 | return 151 | } 152 | c.sharedId = pdu.Message.(*DemandActivePDU).SharedId 153 | c.demandActivePDU = pdu.Message.(*DemandActivePDU) 154 | for _, caps := range pdu.Message.(*DemandActivePDU).CapabilitySets { 155 | c.serverCapabilities[caps.Type()] = caps 156 | } 157 | 158 | c.sendConfirmActivePDU() 159 | c.sendClientFinalizeSynchronizePDU() 160 | c.transport.Once("data", c.recvServerSynchronizePDU) 161 | } 162 | 163 | func (c *Client) sendConfirmActivePDU() { 164 | glog.Debug("PDU start sendConfirmActivePDU") 165 | 166 | pdu := NewConfirmActivePDU() 167 | 168 | generalCapa := c.clientCapabilities[CAPSTYPE_GENERAL].(*GeneralCapability) 169 | generalCapa.OSMajorType = OSMAJORTYPE_WINDOWS 170 | generalCapa.OSMinorType = OSMINORTYPE_WINDOWS_NT 171 | generalCapa.ExtraFlags = LONG_CREDENTIALS_SUPPORTED | NO_BITMAP_COMPRESSION_HDR | ENC_SALTED_CHECKSUM 172 | //if not self._fastPathSender is None: 173 | generalCapa.ExtraFlags |= FASTPATH_OUTPUT_SUPPORTED 174 | 175 | bitmapCapa := c.clientCapabilities[CAPSTYPE_BITMAP].(*BitmapCapability) 176 | bitmapCapa.PreferredBitsPerPixel = c.clientCoreData.HighColorDepth 177 | bitmapCapa.DesktopWidth = c.clientCoreData.DesktopWidth 178 | bitmapCapa.DesktopHeight = c.clientCoreData.DesktopHeight 179 | 180 | orderCapa := c.clientCapabilities[CAPSTYPE_ORDER].(*OrderCapability) 181 | orderCapa.OrderFlags |= ZEROBOUNDSDELTASSUPPORT 182 | 183 | inputCapa := c.clientCapabilities[CAPSTYPE_INPUT].(*InputCapability) 184 | inputCapa.Flags = INPUT_FLAG_SCANCODES | INPUT_FLAG_MOUSEX | INPUT_FLAG_UNICODE 185 | inputCapa.KeyboardLayout = c.clientCoreData.KbdLayout 186 | inputCapa.KeyboardType = c.clientCoreData.KeyboardType 187 | inputCapa.KeyboardSubType = c.clientCoreData.KeyboardSubType 188 | inputCapa.KeyboardFunctionKey = c.clientCoreData.KeyboardFnKeys 189 | inputCapa.ImeFileName = c.clientCoreData.ImeFileName 190 | 191 | pdu.SharedId = c.sharedId 192 | pdu.NumberCapabilities = c.demandActivePDU.NumberCapabilities 193 | for _, v := range c.clientCapabilities { 194 | glog.Debugf("clientCapabilities: 0x%04x", v.Type()) 195 | pdu.CapabilitySets = append(pdu.CapabilitySets, v) 196 | } 197 | if c.remoteAppMode { 198 | pdu.CapabilitySets = append(pdu.CapabilitySets, c.serverCapabilities[CAPSTYPE_RAIL]) 199 | pdu.CapabilitySets = append(pdu.CapabilitySets, c.serverCapabilities[CAPSTYPE_WINDOW]) 200 | } 201 | pdu.LengthSourceDescriptor = c.demandActivePDU.LengthSourceDescriptor 202 | pdu.SourceDescriptor = c.demandActivePDU.SourceDescriptor 203 | pdu.LengthCombinedCapabilities = c.demandActivePDU.LengthCombinedCapabilities 204 | 205 | c.sendPDU(pdu) 206 | } 207 | 208 | func (c *Client) sendClientFinalizeSynchronizePDU() { 209 | glog.Debug("PDU start sendClientFinalizeSynchronizePDU") 210 | c.sendDataPDU(NewSynchronizeDataPDU(c.channelId)) 211 | c.sendDataPDU(&ControlDataPDU{Action: CTRLACTION_COOPERATE}) 212 | c.sendDataPDU(&ControlDataPDU{Action: CTRLACTION_REQUEST_CONTROL}) 213 | //c.sendDataPDU(&PersistKeyPDU{BBitMask: 0x03}) 214 | c.sendDataPDU(&FontListDataPDU{ListFlags: 0x0003, EntrySize: 0x0032}) 215 | } 216 | 217 | func (c *Client) recvServerSynchronizePDU(s []byte) { 218 | glog.Debug("PDU recvServerSynchronizePDU") 219 | r := bytes.NewReader(s) 220 | pdu, err := readPDU(r) 221 | if err != nil { 222 | glog.Error(err) 223 | return 224 | } 225 | dataPdu, ok := pdu.Message.(*DataPDU) 226 | if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_SYNCHRONIZE { 227 | if ok { 228 | glog.Error("recvServerSynchronizePDU ignore datapdu type2", dataPdu.Header.PDUType2) 229 | } else { 230 | glog.Error("recvServerSynchronizePDU ignore message type", pdu.ShareCtrlHeader.PDUType) 231 | } 232 | glog.Infof("%+v", dataPdu) 233 | c.transport.Once("data", c.recvServerSynchronizePDU) 234 | return 235 | } 236 | c.transport.Once("data", c.recvServerControlCooperatePDU) 237 | } 238 | 239 | func (c *Client) recvServerControlCooperatePDU(s []byte) { 240 | glog.Debug("PDU recvServerControlCooperatePDU") 241 | r := bytes.NewReader(s) 242 | pdu, err := readPDU(r) 243 | if err != nil { 244 | glog.Error(err) 245 | return 246 | } 247 | dataPdu, ok := pdu.Message.(*DataPDU) 248 | if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_CONTROL { 249 | if ok { 250 | glog.Error("recvServerControlCooperatePDU ignore datapdu type2", dataPdu.Header.PDUType2) 251 | } else { 252 | glog.Error("recvServerControlCooperatePDU ignore message type", pdu.ShareCtrlHeader.PDUType) 253 | } 254 | c.transport.Once("data", c.recvServerControlCooperatePDU) 255 | return 256 | } 257 | if dataPdu.Data.(*ControlDataPDU).Action != CTRLACTION_COOPERATE { 258 | glog.Error("recvServerControlCooperatePDU ignore action", dataPdu.Data.(*ControlDataPDU).Action) 259 | c.transport.Once("data", c.recvServerControlCooperatePDU) 260 | return 261 | } 262 | c.transport.Once("data", c.recvServerControlGrantedPDU) 263 | } 264 | 265 | func (c *Client) recvServerControlGrantedPDU(s []byte) { 266 | glog.Debug("PDU recvServerControlGrantedPDU") 267 | r := bytes.NewReader(s) 268 | pdu, err := readPDU(r) 269 | if err != nil { 270 | glog.Error(err) 271 | return 272 | } 273 | dataPdu, ok := pdu.Message.(*DataPDU) 274 | if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_CONTROL { 275 | if ok { 276 | glog.Error("recvServerControlGrantedPDU ignore datapdu type2", dataPdu.Header.PDUType2) 277 | } else { 278 | glog.Error("recvServerControlGrantedPDU ignore message type", pdu.ShareCtrlHeader.PDUType) 279 | } 280 | c.transport.Once("data", c.recvServerControlGrantedPDU) 281 | return 282 | } 283 | if dataPdu.Data.(*ControlDataPDU).Action != CTRLACTION_GRANTED_CONTROL { 284 | glog.Error("recvServerControlGrantedPDU ignore action", dataPdu.Data.(*ControlDataPDU).Action) 285 | c.transport.Once("data", c.recvServerControlGrantedPDU) 286 | return 287 | } 288 | c.transport.Once("data", c.recvServerFontMapPDU) 289 | } 290 | 291 | func (c *Client) recvServerFontMapPDU(s []byte) { 292 | glog.Debug("PDU recvServerFontMapPDU") 293 | r := bytes.NewReader(s) 294 | pdu, err := readPDU(r) 295 | if err != nil { 296 | glog.Error(err) 297 | return 298 | } 299 | dataPdu, ok := pdu.Message.(*DataPDU) 300 | if !ok || dataPdu.Header.PDUType2 != PDUTYPE2_FONTMAP { 301 | if ok { 302 | glog.Error("recvServerFontMapPDU ignore datapdu type2", dataPdu.Header.PDUType2) 303 | } else { 304 | glog.Error("recvServerFontMapPDU ignore message type", pdu.ShareCtrlHeader.PDUType) 305 | } 306 | return 307 | } 308 | c.transport.On("data", c.recvPDU) 309 | c.Emit("ready") 310 | } 311 | 312 | func (c *Client) recvPDU(s []byte) { 313 | glog.Debug("PDU recvPDU", hex.EncodeToString(s)) 314 | r := bytes.NewReader(s) 315 | if r.Len() > 0 { 316 | p, err := readPDU(r) 317 | if err != nil { 318 | glog.Error(err) 319 | return 320 | } 321 | if p.ShareCtrlHeader.PDUType == PDUTYPE_DEACTIVATEALLPDU { 322 | c.transport.On("data", c.recvDemandActivePDU) 323 | } 324 | } 325 | } 326 | 327 | func (c *Client) RecvFastPath(secFlag byte, s []byte) { 328 | //glog.Debug("PDU RecvFastPath", hex.EncodeToString(s)) 329 | glog.Debug("PDU RecvFastPath", secFlag&0x2 != 0) 330 | r := bytes.NewReader(s) 331 | for r.Len() > 0 { 332 | p, err := readFastPathUpdatePDU(r) 333 | if err != nil { 334 | glog.Debug("readFastPathUpdatePDU:", err) 335 | //continue 336 | return 337 | } 338 | if p.UpdateHeader == FASTPATH_UPDATETYPE_BITMAP { 339 | c.Emit("update", p.Data.(*FastPathBitmapUpdateDataPDU).Rectangles) 340 | } 341 | } 342 | } 343 | 344 | type InputEventsInterface interface { 345 | Serialize() []byte 346 | } 347 | 348 | func (c *Client) SendInputEvents(msgType uint16, events []InputEventsInterface) { 349 | pdu := &ClientInputEventPDU{} 350 | pdu.NumEvents = uint16(len(events)) 351 | pdu.SlowPathInputEvents = make([]SlowPathInputEvent, 0, pdu.NumEvents) 352 | for _, in := range events { 353 | seria := in.Serialize() 354 | s := SlowPathInputEvent{0, msgType, len(seria), seria} 355 | pdu.SlowPathInputEvents = append(pdu.SlowPathInputEvents, s) 356 | } 357 | 358 | c.sendDataPDU(pdu) 359 | } 360 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/rfb/rfb.go: -------------------------------------------------------------------------------- 1 | // rfb.go 2 | package rfb 3 | 4 | import ( 5 | "bytes" 6 | "crypto/des" 7 | "encoding/hex" 8 | "fmt" 9 | "github.com/bufsnake/Monkey/pkg/grdp/core" 10 | "github.com/bufsnake/Monkey/pkg/grdp/emission" 11 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 12 | "io" 13 | "log" 14 | "net" 15 | 16 | "github.com/lunixbochs/struc" 17 | ) 18 | 19 | // ProtocolVersion 20 | const ( 21 | RFB003003 = "RFB 003.003\n" 22 | RFB003007 = "RFB 003.007\n" 23 | RFB003008 = "RFB 003.008\n" 24 | ) 25 | 26 | // SecurityType 27 | const ( 28 | SEC_INVALID uint8 = 0 29 | SEC_NONE uint8 = 1 30 | SEC_VNC uint8 = 2 31 | ) 32 | 33 | type RFBConn struct { 34 | emission.Emitter 35 | // The Socket connection to the client 36 | Conn net.Conn 37 | s *ServerInit 38 | NbRect uint16 39 | BitRect *BitRect 40 | } 41 | 42 | func NewRFBConn(s net.Conn) *RFBConn { 43 | fc := &RFBConn{ 44 | Emitter: *emission.NewEmitter(), 45 | Conn: s, 46 | BitRect: new(BitRect), 47 | } 48 | core.StartReadBytes(12, fc, fc.recvProtocolVersion) 49 | 50 | return fc 51 | } 52 | func (fc *RFBConn) Read(b []byte) (n int, err error) { 53 | return fc.Conn.Read(b) 54 | } 55 | 56 | func (fc *RFBConn) Write(data []byte) (n int, err error) { 57 | buff := &bytes.Buffer{} 58 | buff.Write(data) 59 | return fc.Conn.Write(buff.Bytes()) 60 | } 61 | func (fc *RFBConn) Close() error { 62 | return fc.Conn.Close() 63 | } 64 | func (fc *RFBConn) recvProtocolVersion(s []byte, err error) { 65 | version := string(s) 66 | glog.Debug("RFBConn recvProtocolVersion", version, err) 67 | if err != nil { 68 | fc.Emit("error", err) 69 | return 70 | } 71 | fc.Emit("data", version) 72 | 73 | if version == RFB003003 { 74 | fc.Emit("error", fmt.Errorf("%s", "Not Support RFB003003")) 75 | return 76 | //core.StartReadBytes(4, fc, fc.recvSecurityServer) 77 | } else { 78 | core.StartReadBytes(1, fc, fc.checkSecurityList) 79 | } 80 | } 81 | func (fc *RFBConn) checkSecurityList(s []byte, err error) { 82 | r := bytes.NewReader(s) 83 | result, _ := core.ReadUInt8(r) 84 | glog.Debug("RFBConn recvSecurityList", result, err) 85 | 86 | core.StartReadBytes(int(result), fc, fc.recvSecurityList) 87 | } 88 | func (fc *RFBConn) recvSecurityList(s []byte, err error) { 89 | r := bytes.NewReader(s) 90 | secLevel := SEC_VNC 91 | for r.Len() > 0 { 92 | result, _ := core.ReadUInt8(r) 93 | if result == SEC_NONE || result == SEC_VNC { 94 | secLevel = result 95 | break 96 | } 97 | } 98 | 99 | glog.Debug("RFBConn recvSecurityList", secLevel, err) 100 | buff := &bytes.Buffer{} 101 | core.WriteUInt8(secLevel, buff) 102 | fc.Write(buff.Bytes()) 103 | if secLevel == SEC_VNC { 104 | core.StartReadBytes(16, fc, fc.recvVNCChallenge) 105 | } else { 106 | core.StartReadBytes(4, fc, fc.recvSecurityResult) 107 | } 108 | 109 | } 110 | 111 | func fixDesKeyByte(val byte) byte { 112 | var newval byte = 0 113 | for i := 0; i < 8; i++ { 114 | newval <<= 1 115 | newval += (val & 1) 116 | val >>= 1 117 | } 118 | return newval 119 | } 120 | 121 | // fixDesKey will make sure that exactly 8 bytes is used either by truncating or padding with nulls 122 | // The bytes are then bit mirrored and returned 123 | func fixDesKey(key []byte) []byte { 124 | tmp := key 125 | buf := make([]byte, 8) 126 | if len(tmp) <= 8 { 127 | copy(buf, tmp) 128 | } else { 129 | copy(buf, tmp[:8]) 130 | } 131 | for i := 0; i < 8; i++ { 132 | buf[i] = fixDesKeyByte(buf[i]) 133 | } 134 | return buf 135 | } 136 | 137 | func (fc *RFBConn) recvVNCChallenge(s []byte, err error) { 138 | glog.Debug("RFBConn recvVNCChallenge", hex.EncodeToString(s), len(s), err) 139 | key := core.Random(8) 140 | bk, err := des.NewCipher(fixDesKey(key)) 141 | if err != nil { 142 | log.Printf("Error generating authentication cipher: %s\n", err.Error()) 143 | return 144 | } 145 | result := make([]byte, 16) 146 | bk.Encrypt(result, s) //Encrypt first 8 bytes 147 | bk.Encrypt(result[8:], s[8:]) 148 | if err != nil { 149 | fmt.Println(err) 150 | } 151 | fmt.Println(string(result)) 152 | fc.Write(result) 153 | core.StartReadBytes(4, fc, fc.recvSecurityResult) 154 | } 155 | func (fc *RFBConn) recvSecurityResult(s []byte, err error) { 156 | r := bytes.NewReader(s) 157 | result, _ := core.ReadUInt32BE(r) 158 | glog.Debug("RFBConn recvSecurityResult", result, err) 159 | if result == 1 { 160 | fc.Emit("error", fmt.Errorf("%s", "Authentification failed")) 161 | return 162 | } 163 | buff := &bytes.Buffer{} 164 | core.WriteUInt8(0, buff) //share 165 | fc.Write(buff.Bytes()) 166 | core.StartReadBytes(20, fc, fc.recvServerInit) 167 | } 168 | 169 | type ServerInit struct { 170 | Width uint16 `struc:"little"` 171 | Height uint16 `struc:"little"` 172 | PixelFormat *PixelFormat `struc:"little"` 173 | } 174 | 175 | func (fc *RFBConn) recvServerInit(s []byte, err error) { 176 | glog.Debug("RFBConn recvServerInit", len(s), err) 177 | r := bytes.NewReader(s) 178 | si := &ServerInit{} 179 | si.Width, err = core.ReadUint16BE(r) 180 | si.Height, err = core.ReadUint16BE(r) 181 | si.PixelFormat = ReadPixelFormat(r) 182 | glog.Infof("serverInit:%+v, %+v", si, si.PixelFormat) 183 | fc.s = si 184 | fc.BitRect.Pf = si.PixelFormat 185 | core.StartReadBytes(4, fc, fc.checkServerName) 186 | } 187 | func (fc *RFBConn) checkServerName(s []byte, err error) { 188 | r := bytes.NewReader(s) 189 | result, _ := core.ReadUInt32BE(r) 190 | glog.Debug("RFBConn recvSecurityList", result, err) 191 | 192 | core.StartReadBytes(int(result), fc, fc.recvServerName) 193 | } 194 | func (fc *RFBConn) recvServerName(s []byte, err error) { 195 | glog.Debug("RFBConn recvServerName", string(s), err) 196 | //fc.sendPixelFormat() 197 | fc.sendSetEncoding() 198 | fc.sendFramebufferUpdateRequest(0, 0, 0, fc.s.Width, fc.s.Height) 199 | 200 | fc.Emit("ready") 201 | core.StartReadBytes(1, fc, fc.recvServerOrder) 202 | } 203 | 204 | func (fc *RFBConn) sendPixelFormat() { 205 | glog.Debug("sendPixelFormat") 206 | buff := &bytes.Buffer{} 207 | core.WriteUInt8(0, buff) 208 | core.WriteUInt16BE(0, buff) 209 | core.WriteUInt8(0, buff) 210 | err := struc.Pack(buff, NewPixelFormat()) 211 | if err != nil { 212 | fc.Emit("error", err) 213 | return 214 | } 215 | fc.Write(buff.Bytes()) 216 | } 217 | func (fc *RFBConn) sendSetEncoding() { 218 | glog.Debug("sendSetEncoding") 219 | buff := &bytes.Buffer{} 220 | core.WriteUInt8(2, buff) 221 | core.WriteUInt8(0, buff) 222 | core.WriteUInt16BE(1, buff) 223 | core.WriteUInt32BE(0, buff) 224 | fc.Write(buff.Bytes()) 225 | } 226 | 227 | type FrameBufferUpdateRequest struct { 228 | Incremental uint8 229 | X uint16 230 | Y uint16 231 | Width uint16 232 | Height uint16 233 | } 234 | 235 | func (fc *RFBConn) sendFramebufferUpdateRequest(Incremental uint8, 236 | X uint16, 237 | Y uint16, 238 | Width uint16, 239 | Height uint16) { 240 | glog.Debug("sendFramebufferUpdateRequest") 241 | buff := &bytes.Buffer{} 242 | core.WriteUInt8(3, buff) 243 | core.WriteUInt8(Incremental, buff) 244 | core.WriteUInt16BE(X, buff) 245 | core.WriteUInt16BE(Y, buff) 246 | core.WriteUInt16BE(Width, buff) 247 | core.WriteUInt16BE(Height, buff) 248 | fc.Write(buff.Bytes()) 249 | } 250 | func (fc *RFBConn) recvServerOrder(s []byte, err error) { 251 | glog.Debug("RFBConn recvServerOrder", hex.EncodeToString(s), err) 252 | r := bytes.NewReader(s) 253 | packetType, _ := core.ReadUInt8(r) 254 | switch packetType { 255 | case 0: 256 | core.StartReadBytes(3, fc, fc.recvFrameBufferUpdateHeader) 257 | case 2: 258 | //TODO 259 | case 3: 260 | core.StartReadBytes(7, fc, fc.recvServerCutTextHeader) 261 | default: 262 | glog.Errorf("Unknown message type %s", packetType) 263 | } 264 | 265 | } 266 | 267 | type BitRect struct { 268 | Rects []Rectangles 269 | Pf *PixelFormat 270 | } 271 | 272 | type Rectangles struct { 273 | Rect *Rectangle 274 | Data []byte 275 | } 276 | 277 | func (fc *RFBConn) recvFrameBufferUpdateHeader(s []byte, err error) { 278 | glog.Debug("RFBConn recvFrameBufferUpdateHeader", hex.EncodeToString(s), err) 279 | r := bytes.NewReader(s) 280 | core.ReadUInt8(r) 281 | NbRect, _ := core.ReadUint16BE(r) 282 | fc.NbRect = NbRect 283 | fc.BitRect.Rects = make([]Rectangles, fc.NbRect) 284 | if NbRect == 0 { 285 | return 286 | } 287 | glog.Info("NbRect:", NbRect) 288 | core.StartReadBytes(12, fc, fc.recvRectHeader) 289 | } 290 | 291 | type Rectangle struct { 292 | X uint16 `struc:"little"` 293 | Y uint16 `struc:"little"` 294 | Width uint16 `struc:"little"` 295 | Height uint16 `struc:"little"` 296 | Encoding uint32 `struc:"little"` 297 | } 298 | 299 | func (fc *RFBConn) recvRectHeader(s []byte, err error) { 300 | glog.Debug("RFBConn recvRectHeader", hex.EncodeToString(s), err) 301 | r := bytes.NewReader(s) 302 | x, err := core.ReadUint16BE(r) 303 | y, err := core.ReadUint16BE(r) 304 | w, err := core.ReadUint16BE(r) 305 | h, err := core.ReadUint16BE(r) 306 | e, err := core.ReadUInt32BE(r) 307 | rect := &Rectangle{x, y, w, h, e} 308 | 309 | fc.BitRect.Rects[fc.NbRect-1].Rect = rect 310 | glog.Infof("rect:%+v, len=%d", rect, int(rect.Width)*int(rect.Height)*4) 311 | core.StartReadBytes(int(rect.Width)*int(rect.Height)*4, fc, fc.recvRectBody) 312 | } 313 | func (fc *RFBConn) recvRectBody(s []byte, err error) { 314 | glog.Debug("RFBConn recvRectBody", hex.EncodeToString(s), err) 315 | fc.BitRect.Rects[fc.NbRect-1].Data = s 316 | fc.NbRect-- 317 | glog.Info("fc.NbRect:", fc.NbRect) 318 | if fc.NbRect == 0 { 319 | fc.Emit("update", fc.BitRect) 320 | fc.sendFramebufferUpdateRequest(1, 0, 0, fc.s.Width, fc.s.Height) 321 | core.StartReadBytes(1, fc, fc.recvServerOrder) 322 | } else { 323 | core.StartReadBytes(12, fc, fc.recvRectHeader) 324 | } 325 | } 326 | 327 | type ServerCutTextHeader struct { 328 | Padding [3]byte `struc:"little"` 329 | Size uint32 `struc:"little"` 330 | } 331 | 332 | func (fc *RFBConn) recvServerCutTextHeader(s []byte, err error) { 333 | glog.Debug("RFBConn recvServerCutTextHeader", string(s), err) 334 | r := bytes.NewReader(s) 335 | header := &ServerCutTextHeader{} 336 | err = struc.Unpack(r, header) 337 | if err != nil { 338 | fc.Emit("error", err) 339 | return 340 | } 341 | 342 | core.StartReadBytes(int(header.Size), fc, fc.recvServerCutTextBody) 343 | } 344 | func (fc *RFBConn) recvServerCutTextBody(s []byte, err error) { 345 | glog.Debug("RFBConn recvServerCutTextBody", string(s), err) 346 | fc.Emit("CutText", s) 347 | core.StartReadBytes(1, fc, fc.recvServerOrder) 348 | } 349 | 350 | type PixelFormat struct { 351 | BitsPerPixel uint8 `struc:"little"` 352 | Depth uint8 `struc:"little"` 353 | BigEndianFlag uint8 `struc:"little"` 354 | TrueColorFlag uint8 `struc:"little"` 355 | RedMax uint16 `struc:"little"` 356 | GreenMax uint16 `struc:"little"` 357 | BlueMax uint16 `struc:"little"` 358 | RedShift uint8 `struc:"little"` 359 | GreenShift uint8 `struc:"little"` 360 | BlueShift uint8 `struc:"little"` 361 | Padding uint16 `struc:"little"` 362 | Padding1 uint8 `struc:"little"` 363 | } 364 | 365 | func ReadPixelFormat(r io.Reader) *PixelFormat { 366 | p := NewPixelFormat() 367 | p.BitsPerPixel, _ = core.ReadUInt8(r) 368 | p.Depth, _ = core.ReadUInt8(r) 369 | p.BigEndianFlag, _ = core.ReadUInt8(r) 370 | p.TrueColorFlag, _ = core.ReadUInt8(r) 371 | p.RedMax, _ = core.ReadUint16BE(r) 372 | p.GreenMax, _ = core.ReadUint16BE(r) 373 | p.BlueMax, _ = core.ReadUint16BE(r) 374 | p.RedShift, _ = core.ReadUInt8(r) 375 | p.GreenShift, _ = core.ReadUInt8(r) 376 | p.BlueShift, _ = core.ReadUInt8(r) 377 | p.Padding, _ = core.ReadUint16BE(r) 378 | p.Padding1, _ = core.ReadUInt8(r) 379 | 380 | return p 381 | } 382 | func NewPixelFormat() *PixelFormat { 383 | return &PixelFormat{ 384 | 32, 24, 0, 1, 65280, 65280, 65280, 16, 8, 0, 0, 0, 385 | } 386 | } 387 | 388 | type RFB struct { 389 | core.Transport 390 | Version string 391 | SecurityLevel uint8 392 | ServerName string 393 | PixelFormat *PixelFormat 394 | NbRect int 395 | CurrentRect *Rectangle 396 | Password string 397 | } 398 | 399 | func NewRFB(t core.Transport) *RFB { 400 | fb := &RFB{t, RFB003008, SEC_INVALID, "", NewPixelFormat(), 0, &Rectangle{}, ""} 401 | 402 | fb.Once("data", fb.recvProtocolVersion) 403 | 404 | return fb 405 | } 406 | 407 | func (fb *RFB) recvProtocolVersion(version string) { 408 | if version != RFB003003 || version != RFB003007 || version != RFB003008 { 409 | version = RFB003008 410 | } 411 | glog.Infof("version:%s", version) 412 | b := &bytes.Buffer{} 413 | b.WriteString(version) 414 | fb.Write(b.Bytes()) 415 | } 416 | 417 | type KeyEvent struct { 418 | DownFlag uint8 `struc:"little"` 419 | Padding uint16 `struc:"little"` 420 | Key uint32 `struc:"little"` 421 | } 422 | 423 | func (fb *RFB) SendKeyEvent(k *KeyEvent) { 424 | b := &bytes.Buffer{} 425 | core.WriteUInt8(4, b) 426 | core.WriteUInt8(k.DownFlag, b) 427 | core.WriteUInt16BE(k.Padding, b) 428 | core.WriteUInt32BE(k.Key, b) 429 | fmt.Println(b.Bytes()) 430 | fb.Write(b.Bytes()) 431 | } 432 | 433 | type PointerEvent struct { 434 | Mask uint8 `struc:"little"` 435 | XPos uint16 `struc:"little"` 436 | YPos uint16 `struc:"little"` 437 | } 438 | 439 | func (fb *RFB) SendPointEvent(p *PointerEvent) { 440 | b := &bytes.Buffer{} 441 | core.WriteUInt8(5, b) 442 | core.WriteUInt8(p.Mask, b) 443 | core.WriteUInt16BE(p.XPos, b) 444 | core.WriteUInt16BE(p.YPos, b) 445 | fmt.Println(b.Bytes()) 446 | fb.Write(b.Bytes()) 447 | } 448 | 449 | type ClientCutText struct { 450 | Padding uint16 `struc:"little"` 451 | Padding1 uint8 `struc:"little"` 452 | Size uint32 `struc:"little"` 453 | Message string `struc:"little"` 454 | } 455 | 456 | func (fb *RFB) SendClientCutText(t *ClientCutText) { 457 | b := &bytes.Buffer{} 458 | core.WriteUInt8(6, b) 459 | struc.Pack(b, t) 460 | fb.Write(b.Bytes()) 461 | } 462 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/t125/mcs.go: -------------------------------------------------------------------------------- 1 | package t125 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "errors" 7 | "fmt" 8 | "github.com/bufsnake/Monkey/pkg/grdp/core" 9 | "github.com/bufsnake/Monkey/pkg/grdp/emission" 10 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 11 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/t125/ber" 12 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/t125/gcc" 13 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/t125/per" 14 | "io" 15 | "reflect" 16 | ) 17 | 18 | // take idea from https://github.com/Madnikulin50/gordp 19 | 20 | // Multiple Channel Service layer 21 | 22 | type MCSMessage uint8 23 | 24 | const ( 25 | MCS_TYPE_CONNECT_INITIAL MCSMessage = 0x65 26 | MCS_TYPE_CONNECT_RESPONSE = 0x66 27 | ) 28 | 29 | type MCSDomainPDU uint16 30 | 31 | const ( 32 | ERECT_DOMAIN_REQUEST MCSDomainPDU = 1 33 | DISCONNECT_PROVIDER_ULTIMATUM = 8 34 | ATTACH_USER_REQUEST = 10 35 | ATTACH_USER_CONFIRM = 11 36 | CHANNEL_JOIN_REQUEST = 14 37 | CHANNEL_JOIN_CONFIRM = 15 38 | SEND_DATA_REQUEST = 25 39 | SEND_DATA_INDICATION = 26 40 | ) 41 | 42 | const ( 43 | MCS_GLOBAL_CHANNEL uint16 = 1003 44 | MCS_USERCHANNEL_BASE = 1001 45 | ) 46 | 47 | /** 48 | * Format MCS PDULayer header packet 49 | * @param mcsPdu {integer} 50 | * @param options {integer} 51 | * @returns {type.UInt8} headers 52 | */ 53 | func writeMCSPDUHeader(mcsPdu MCSDomainPDU, options uint8, w io.Writer) { 54 | core.WriteUInt8((uint8(mcsPdu)<<2)|options, w) 55 | } 56 | 57 | func readMCSPDUHeader(options uint8, mcsPdu MCSDomainPDU) bool { 58 | return (options >> 2) == uint8(mcsPdu) 59 | } 60 | 61 | type DomainParameters struct { 62 | MaxChannelIds int 63 | MaxUserIds int 64 | MaxTokenIds int 65 | NumPriorities int 66 | MinThoughput int 67 | MaxHeight int 68 | MaxMCSPDUsize int 69 | ProtocolVersion int 70 | } 71 | 72 | /** 73 | * @see http://www.itu.int/rec/T-REC-T.125-199802-I/en page 25 74 | * @returns {asn1.univ.Sequence} 75 | */ 76 | func NewDomainParameters( 77 | maxChannelIds int, 78 | maxUserIds int, 79 | maxTokenIds int, 80 | numPriorities int, 81 | minThoughput int, 82 | maxHeight int, 83 | maxMCSPDUsize int, 84 | protocolVersion int) *DomainParameters { 85 | return &DomainParameters{maxChannelIds, maxUserIds, maxTokenIds, 86 | numPriorities, minThoughput, maxHeight, maxMCSPDUsize, protocolVersion} 87 | } 88 | 89 | func (d *DomainParameters) BER() []byte { 90 | buff := &bytes.Buffer{} 91 | ber.WriteInteger(d.MaxChannelIds, buff) 92 | ber.WriteInteger(d.MaxUserIds, buff) 93 | ber.WriteInteger(d.MaxTokenIds, buff) 94 | ber.WriteInteger(1, buff) 95 | ber.WriteInteger(0, buff) 96 | ber.WriteInteger(1, buff) 97 | ber.WriteInteger(d.MaxMCSPDUsize, buff) 98 | ber.WriteInteger(2, buff) 99 | return buff.Bytes() 100 | } 101 | 102 | func ReadDomainParameters(r io.Reader) (*DomainParameters, error) { 103 | if !ber.ReadUniversalTag(ber.TAG_SEQUENCE, true, r) { 104 | return nil, errors.New("bad BER tags") 105 | } 106 | d := &DomainParameters{} 107 | ber.ReadLength(r) 108 | 109 | d.MaxChannelIds, _ = ber.ReadInteger(r) 110 | d.MaxUserIds, _ = ber.ReadInteger(r) 111 | d.MaxTokenIds, _ = ber.ReadInteger(r) 112 | ber.ReadInteger(r) 113 | ber.ReadInteger(r) 114 | ber.ReadInteger(r) 115 | d.MaxMCSPDUsize, _ = ber.ReadInteger(r) 116 | ber.ReadInteger(r) 117 | return d, nil 118 | } 119 | 120 | /** 121 | * @see http://www.itu.int/rec/T-REC-T.125-199802-I/en page 25 122 | * @param userData {Buffer} 123 | * @returns {asn1.univ.Sequence} 124 | */ 125 | type ConnectInitial struct { 126 | CallingDomainSelector []byte 127 | CalledDomainSelector []byte 128 | UpwardFlag bool 129 | TargetParameters DomainParameters 130 | MinimumParameters DomainParameters 131 | MaximumParameters DomainParameters 132 | UserData []byte 133 | } 134 | 135 | func NewConnectInitial(userData []byte) ConnectInitial { 136 | return ConnectInitial{[]byte{0x1}, 137 | []byte{0x1}, 138 | true, 139 | *NewDomainParameters(34, 2, 0, 1, 0, 1, 0xffff, 2), 140 | *NewDomainParameters(1, 1, 1, 1, 0, 1, 0x420, 2), 141 | *NewDomainParameters(0xffff, 0xfc17, 0xffff, 1, 0, 1, 0xffff, 2), 142 | userData} 143 | } 144 | 145 | func (c *ConnectInitial) BER() []byte { 146 | buff := &bytes.Buffer{} 147 | ber.WriteOctetstring(string(c.CallingDomainSelector), buff) 148 | ber.WriteOctetstring(string(c.CalledDomainSelector), buff) 149 | ber.WriteBoolean(c.UpwardFlag, buff) 150 | ber.WriteEncodedDomainParams(c.TargetParameters.BER(), buff) 151 | ber.WriteEncodedDomainParams(c.MinimumParameters.BER(), buff) 152 | ber.WriteEncodedDomainParams(c.MaximumParameters.BER(), buff) 153 | ber.WriteOctetstring(string(c.UserData), buff) 154 | return buff.Bytes() 155 | } 156 | 157 | /** 158 | * @see http://www.itu.int/rec/T-REC-T.125-199802-I/en page 25 159 | * @returns {asn1.univ.Sequence} 160 | */ 161 | 162 | type ConnectResponse struct { 163 | result uint8 164 | calledConnectId int 165 | domainParameters *DomainParameters 166 | userData []byte 167 | } 168 | 169 | func NewConnectResponse(userData []byte) *ConnectResponse { 170 | return &ConnectResponse{0, 171 | 0, 172 | NewDomainParameters(22, 3, 0, 1, 0, 1, 0xfff8, 2), 173 | userData} 174 | } 175 | 176 | func ReadConnectResponse(r io.Reader) (*ConnectResponse, error) { 177 | c := &ConnectResponse{} 178 | var err error 179 | _, err = ber.ReadApplicationTag(MCS_TYPE_CONNECT_RESPONSE, r) 180 | if err != nil { 181 | return nil, err 182 | } 183 | c.result, err = ber.ReadEnumerated(r) 184 | if err != nil { 185 | return nil, err 186 | } 187 | 188 | c.calledConnectId, err = ber.ReadInteger(r) 189 | c.domainParameters, err = ReadDomainParameters(r) 190 | if err != nil { 191 | return nil, err 192 | } 193 | if !ber.ReadUniversalTag(ber.TAG_OCTET_STRING, false, r) { 194 | return nil, errors.New("invalid expected BER tag") 195 | } 196 | dataLen, _ := ber.ReadLength(r) 197 | c.userData, err = core.ReadBytes(dataLen, r) 198 | return c, err 199 | } 200 | 201 | type MCSChannelInfo struct { 202 | ID uint16 203 | Name string 204 | } 205 | 206 | type MCS struct { 207 | emission.Emitter 208 | transport core.Transport 209 | recvOpCode MCSDomainPDU 210 | sendOpCode MCSDomainPDU 211 | channels []MCSChannelInfo 212 | } 213 | 214 | func NewMCS(t core.Transport, recvOpCode MCSDomainPDU, sendOpCode MCSDomainPDU) *MCS { 215 | m := &MCS{ 216 | *emission.NewEmitter(), 217 | t, 218 | recvOpCode, 219 | sendOpCode, 220 | []MCSChannelInfo{{MCS_GLOBAL_CHANNEL, "global"}}, 221 | } 222 | 223 | m.transport.On("close", func() { 224 | m.Emit("close") 225 | }).On("error", func(err error) { 226 | m.Emit("error", err) 227 | }) 228 | return m 229 | } 230 | 231 | func (x *MCS) Read(b []byte) (n int, err error) { 232 | return x.transport.Read(b) 233 | } 234 | 235 | func (x *MCS) Write(b []byte) (n int, err error) { 236 | return x.transport.Write(b) 237 | } 238 | 239 | func (m *MCS) Close() error { 240 | return m.transport.Close() 241 | } 242 | 243 | type MCSClient struct { 244 | *MCS 245 | clientCoreData *gcc.ClientCoreData 246 | clientNetworkData *gcc.ClientNetworkData 247 | clientSecurityData *gcc.ClientSecurityData 248 | 249 | serverCoreData *gcc.ServerCoreData 250 | serverNetworkData *gcc.ServerNetworkData 251 | serverSecurityData *gcc.ServerSecurityData 252 | 253 | channelsConnected int 254 | userId uint16 255 | nbChannelRequested int 256 | } 257 | 258 | func NewMCSClient(t core.Transport) *MCSClient { 259 | c := &MCSClient{ 260 | MCS: NewMCS(t, SEND_DATA_INDICATION, SEND_DATA_REQUEST), 261 | clientCoreData: gcc.NewClientCoreData(), 262 | clientNetworkData: gcc.NewClientNetworkData(), 263 | clientSecurityData: gcc.NewClientSecurityData(), 264 | userId: 1 + MCS_USERCHANNEL_BASE, 265 | } 266 | c.transport.On("connect", c.connect) 267 | return c 268 | } 269 | 270 | func (c *MCSClient) SetClientCoreData(width, height uint16) { 271 | c.clientCoreData.DesktopWidth = width 272 | c.clientCoreData.DesktopHeight = height 273 | } 274 | 275 | func (c *MCSClient) connect(selectedProtocol uint32) { 276 | glog.Debug("mcs client on connect", selectedProtocol) 277 | c.clientCoreData.ServerSelectedProtocol = selectedProtocol 278 | 279 | // sendConnectInitial 280 | userDataBuff := bytes.Buffer{} 281 | userDataBuff.Write(c.clientCoreData.Block()) 282 | userDataBuff.Write(c.clientNetworkData.Block()) 283 | userDataBuff.Write(c.clientSecurityData.Block()) 284 | 285 | ccReq := gcc.MakeConferenceCreateRequest(userDataBuff.Bytes()) 286 | connectInitial := NewConnectInitial(ccReq) 287 | connectInitialBerEncoded := connectInitial.BER() 288 | 289 | dataBuff := &bytes.Buffer{} 290 | ber.WriteApplicationTag(uint8(MCS_TYPE_CONNECT_INITIAL), len(connectInitialBerEncoded), dataBuff) 291 | dataBuff.Write(connectInitialBerEncoded) 292 | 293 | _, err := c.transport.Write(dataBuff.Bytes()) 294 | if err != nil { 295 | c.Emit("error", errors.New(fmt.Sprintf("mcs sendConnectInitial write error %v", err))) 296 | return 297 | } 298 | glog.Debug("mcs wait for data event") 299 | c.transport.Once("data", c.recvConnectResponse) 300 | } 301 | 302 | func (c *MCSClient) recvConnectResponse(s []byte) { 303 | glog.Debug("mcs recvConnectResponse", hex.EncodeToString(s)) 304 | cResp, err := ReadConnectResponse(bytes.NewReader(s)) 305 | if err != nil { 306 | c.Emit("error", errors.New(fmt.Sprintf("ReadConnectResponse %v", err))) 307 | return 308 | } 309 | // record server gcc block 310 | serverSettings := gcc.ReadConferenceCreateResponse(cResp.userData) 311 | 312 | for _, v := range serverSettings { 313 | 314 | switch v.(type) { 315 | case *gcc.ServerSecurityData: 316 | c.serverSecurityData = v.(*gcc.ServerSecurityData) 317 | 318 | case *gcc.ServerCoreData: 319 | c.serverCoreData = v.(*gcc.ServerCoreData) 320 | 321 | case *gcc.ServerNetworkData: 322 | c.serverNetworkData = v.(*gcc.ServerNetworkData) 323 | 324 | default: 325 | err := errors.New(fmt.Sprintf("unhandle server gcc block %v", reflect.TypeOf(v))) 326 | glog.Error(err) 327 | c.Emit("error", err) 328 | return 329 | } 330 | } 331 | glog.Debugf("serverSecurityData: %+v", c.serverSecurityData) 332 | glog.Debugf("serverCoreData: %+v", c.serverCoreData) 333 | glog.Debugf("serverNetworkData: %+v", c.serverNetworkData) 334 | glog.Debug("mcs sendErectDomainRequest") 335 | c.sendErectDomainRequest() 336 | 337 | glog.Debug("mcs sendAttachUserRequest") 338 | c.sendAttachUserRequest() 339 | 340 | c.transport.Once("data", c.recvAttachUserConfirm) 341 | } 342 | 343 | func (c *MCSClient) sendErectDomainRequest() { 344 | buff := &bytes.Buffer{} 345 | writeMCSPDUHeader(ERECT_DOMAIN_REQUEST, 0, buff) 346 | per.WriteInteger(0, buff) 347 | per.WriteInteger(0, buff) 348 | c.transport.Write(buff.Bytes()) 349 | } 350 | 351 | func (c *MCSClient) sendAttachUserRequest() { 352 | buff := &bytes.Buffer{} 353 | writeMCSPDUHeader(ATTACH_USER_REQUEST, 0, buff) 354 | c.transport.Write(buff.Bytes()) 355 | } 356 | 357 | func (c *MCSClient) recvAttachUserConfirm(s []byte) { 358 | glog.Debug("mcs recvAttachUserConfirm", hex.EncodeToString(s)) 359 | r := bytes.NewReader(s) 360 | 361 | option, err := core.ReadUInt8(r) 362 | if err != nil { 363 | c.Emit("error", err) 364 | return 365 | } 366 | 367 | if !readMCSPDUHeader(option, ATTACH_USER_CONFIRM) { 368 | c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_BAD_HEADER")) 369 | return 370 | } 371 | 372 | e, err := per.ReadEnumerates(r) 373 | if err != nil { 374 | c.Emit("error", err) 375 | return 376 | } 377 | if e != 0 { 378 | c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_SERVER_REJECT_USER'")) 379 | return 380 | } 381 | 382 | userId, _ := per.ReadInteger16(r) 383 | userId += MCS_USERCHANNEL_BASE 384 | c.userId = userId 385 | 386 | c.channels = append(c.channels, MCSChannelInfo{userId, "user"}) 387 | c.connectChannels() 388 | } 389 | 390 | func (c *MCSClient) connectChannels() { 391 | glog.Debug("mcs connectChannels:", c.channelsConnected, ":", len(c.channels)) 392 | if c.channelsConnected == len(c.channels) { 393 | //if c.nbChannelRequested < int(c.serverNetworkData.ChannelCount) { 394 | //static virtual channel 395 | //chanId := c.serverNetworkData.ChannelIdArray[c.nbChannelRequested] 396 | //c.nbChannelRequested++ 397 | //c.sendChannelJoinRequest(chanId) 398 | //return 399 | //} 400 | c.transport.On("data", c.recvData) 401 | // send client and sever gcc informations callback to sec 402 | clientData := make([]interface{}, 0) 403 | clientData = append(clientData, c.clientCoreData) 404 | clientData = append(clientData, c.clientSecurityData) 405 | clientData = append(clientData, c.clientNetworkData) 406 | 407 | serverData := make([]interface{}, 0) 408 | 409 | serverData = append(serverData, c.serverCoreData) 410 | serverData = append(serverData, c.serverSecurityData) 411 | glog.Debug("msc connectChannels callback to sec") 412 | c.Emit("connect", clientData, serverData, c.userId, c.channels) 413 | return 414 | } 415 | 416 | // sendChannelJoinRequest 417 | glog.Debug("sendChannelJoinRequest:", c.channels[c.channelsConnected].Name) 418 | c.sendChannelJoinRequest(c.channels[c.channelsConnected].ID) 419 | c.channelsConnected += 1 420 | 421 | c.transport.Once("data", c.recvChannelJoinConfirm) 422 | } 423 | 424 | func (c *MCSClient) sendChannelJoinRequest(channelId uint16) { 425 | glog.Debug("mcs sendChannelJoinRequest", channelId) 426 | buff := &bytes.Buffer{} 427 | writeMCSPDUHeader(CHANNEL_JOIN_REQUEST, 0, buff) 428 | per.WriteInteger16(c.userId-MCS_USERCHANNEL_BASE, buff) 429 | per.WriteInteger16(channelId, buff) 430 | c.transport.Write(buff.Bytes()) 431 | } 432 | 433 | func (c *MCSClient) recvData(s []byte) { 434 | glog.Debug("msc on data recvData:", hex.EncodeToString(s)) 435 | 436 | r := bytes.NewReader(s) 437 | option, err := core.ReadUInt8(r) 438 | if err != nil { 439 | c.Emit("error", err) 440 | return 441 | } 442 | 443 | if readMCSPDUHeader(option, DISCONNECT_PROVIDER_ULTIMATUM) { 444 | c.Emit("error", errors.New("MCS DISCONNECT_PROVIDER_ULTIMATUM")) 445 | c.transport.Close() 446 | return 447 | } else if !readMCSPDUHeader(option, c.recvOpCode) { 448 | c.Emit("error", errors.New("Invalid expected MCS opcode receive data")) 449 | return 450 | } 451 | 452 | userId, _ := per.ReadInteger16(r) 453 | userId += MCS_USERCHANNEL_BASE 454 | 455 | channelId, _ := per.ReadInteger16(r) 456 | per.ReadEnumerates(r) 457 | size, _ := per.ReadLength(r) 458 | 459 | // channel ID doesn't match a requested layer 460 | found := false 461 | channelName := "" 462 | for _, channel := range c.channels { 463 | if channel.ID == channelId { 464 | found = true 465 | channelName = channel.Name 466 | break 467 | } 468 | } 469 | if !found { 470 | glog.Error("mcs receive data for an unconnected layer") 471 | return 472 | } 473 | left, err := core.ReadBytes(int(size), r) 474 | if err != nil { 475 | c.Emit("error", errors.New(fmt.Sprintf("mcs recvData get data error %v", err))) 476 | return 477 | } 478 | glog.Debug("mcs emit channel", channelName, left) 479 | c.Emit(channelName, left) 480 | //c.Emit(channelName, s) 481 | } 482 | 483 | func (c *MCSClient) recvChannelJoinConfirm(s []byte) { 484 | glog.Debug("mcs recvChannelJoinConfirm", hex.EncodeToString(s)) 485 | r := bytes.NewReader(s) 486 | option, err := core.ReadUInt8(r) 487 | if err != nil { 488 | c.Emit("error", err) 489 | return 490 | } 491 | 492 | if !readMCSPDUHeader(option, CHANNEL_JOIN_CONFIRM) { 493 | c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_WAIT_CHANNEL_JOIN_CONFIRM")) 494 | return 495 | } 496 | 497 | confirm, _ := per.ReadEnumerates(r) 498 | userId, _ := per.ReadInteger16(r) 499 | userId += MCS_USERCHANNEL_BASE 500 | if c.userId != userId { 501 | c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_INVALID_USER_ID")) 502 | return 503 | } 504 | 505 | channelId, _ := per.ReadInteger16(r) 506 | if (confirm != 0) && (channelId == uint16(MCS_GLOBAL_CHANNEL) || channelId == c.userId) { 507 | c.Emit("error", errors.New("NODE_RDP_PROTOCOL_T125_MCS_SERVER_MUST_CONFIRM_STATIC_CHANNEL")) 508 | return 509 | } 510 | 511 | /*if confirm == 0 { 512 | for i := 0; i < int(c.serverNetworkData.ChannelCount); i++ { 513 | if channelId == c.serverNetworkData.ChannelIdArray[i] { 514 | c.channels[channelId] = c.serverNetworkData.ChannelIdArray[i][1] 515 | } 516 | } 517 | }*/ 518 | 519 | c.connectChannels() 520 | } 521 | 522 | func (c *MCSClient) SendToChannel(data []byte, channelId uint16) (n int, err error) { 523 | buff := &bytes.Buffer{} 524 | writeMCSPDUHeader(c.sendOpCode, 0, buff) 525 | per.WriteInteger16(c.userId-MCS_USERCHANNEL_BASE, buff) 526 | per.WriteInteger16(channelId, buff) 527 | core.WriteUInt8(0x70, buff) 528 | per.WriteLength(len(data), buff) 529 | core.WriteBytes(data, buff) 530 | glog.Debug("MCSClient write", hex.EncodeToString(buff.Bytes())) 531 | return c.transport.Write(buff.Bytes()) 532 | } 533 | 534 | func (c *MCSClient) Write(data []byte) (n int, err error) { 535 | return c.SendToChannel(data, c.channels[0].ID) 536 | } 537 | -------------------------------------------------------------------------------- /pkg/grdp/protocol/t125/gcc/gcc.go: -------------------------------------------------------------------------------- 1 | package gcc 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "github.com/bufsnake/Monkey/pkg/grdp/core" 7 | "github.com/bufsnake/Monkey/pkg/grdp/glog" 8 | "github.com/bufsnake/Monkey/pkg/grdp/protocol/t125/per" 9 | "io" 10 | "os" 11 | 12 | "github.com/lunixbochs/struc" 13 | ) 14 | 15 | var t124_02_98_oid = []byte{0, 0, 20, 124, 0, 1} 16 | var h221_cs_key = "Duca" 17 | var h221_sc_key = "McDn" 18 | 19 | /** 20 | * @see http://msdn.microsoft.com/en-us/library/cc240509.aspx 21 | */ 22 | type Message uint16 23 | 24 | const ( 25 | //server -> client 26 | SC_CORE Message = 0x0C01 27 | SC_SECURITY = 0x0C02 28 | SC_NET = 0x0C03 29 | //client -> server 30 | CS_CORE = 0xC001 31 | CS_SECURITY = 0xC002 32 | CS_NET = 0xC003 33 | CS_CLUSTER = 0xC004 34 | CS_MONITOR = 0xC005 35 | ) 36 | 37 | /** 38 | * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx 39 | */ 40 | type ColorDepth uint16 41 | 42 | const ( 43 | RNS_UD_COLOR_8BPP ColorDepth = 0xCA01 44 | RNS_UD_COLOR_16BPP_555 = 0xCA02 45 | RNS_UD_COLOR_16BPP_565 = 0xCA03 46 | RNS_UD_COLOR_24BPP = 0xCA04 47 | ) 48 | 49 | /** 50 | * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx 51 | */ 52 | type HighColor uint16 53 | 54 | const ( 55 | HIGH_COLOR_4BPP HighColor = 0x0004 56 | HIGH_COLOR_8BPP = 0x0008 57 | HIGH_COLOR_15BPP = 0x000f 58 | HIGH_COLOR_16BPP = 0x0010 59 | HIGH_COLOR_24BPP = 0x0018 60 | ) 61 | 62 | /** 63 | * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx 64 | */ 65 | type Support uint16 66 | 67 | const ( 68 | RNS_UD_24BPP_SUPPORT uint16 = 0x0001 69 | RNS_UD_16BPP_SUPPORT = 0x0002 70 | RNS_UD_15BPP_SUPPORT = 0x0004 71 | RNS_UD_32BPP_SUPPORT = 0x0008 72 | ) 73 | 74 | /** 75 | * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx 76 | */ 77 | type CapabilityFlag uint16 78 | 79 | const ( 80 | RNS_UD_CS_SUPPORT_ERRINFO_PDU uint16 = 0x0001 81 | RNS_UD_CS_WANT_32BPP_SESSION = 0x0002 82 | RNS_UD_CS_SUPPORT_STATUSINFO_PDU = 0x0004 83 | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS = 0x0008 84 | RNS_UD_CS_UNUSED = 0x0010 85 | RNS_UD_CS_VALID_CONNECTION_TYPE = 0x0020 86 | RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU = 0x0040 87 | RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT = 0x0080 88 | RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL = 0x0100 89 | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE = 0x0200 90 | RNS_UD_CS_SUPPORT_HEARTBEAT_PDU = 0x0400 91 | ) 92 | 93 | /** 94 | * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx 95 | */ 96 | type ConnectionType uint8 97 | 98 | const ( 99 | CONNECTION_TYPE_MODEM ConnectionType = 0x01 100 | CONNECTION_TYPE_BROADBAND_LOW = 0x02 101 | CONNECTION_TYPE_SATELLITEV = 0x03 102 | CONNECTION_TYPE_BROADBAND_HIGH = 0x04 103 | CONNECTION_TYPE_WAN = 0x05 104 | CONNECTION_TYPE_LAN = 0x06 105 | CONNECTION_TYPE_AUTODETECT = 0x07 106 | ) 107 | 108 | /** 109 | * @see http://msdn.microsoft.com/en-us/library/cc240510.aspx 110 | */ 111 | type VERSION uint32 112 | 113 | const ( 114 | RDP_VERSION_4 VERSION = 0x00080001 115 | RDP_VERSION_5_PLUS = 0x00080004 116 | ) 117 | 118 | type Sequence uint16 119 | 120 | const ( 121 | RNS_UD_SAS_DEL Sequence = 0xAA03 122 | ) 123 | 124 | /** 125 | * @see http://msdn.microsoft.com/en-us/library/cc240511.aspx 126 | */ 127 | type EncryptionMethod uint32 128 | 129 | const ( 130 | ENCRYPTION_FLAG_40BIT uint32 = 0x00000001 131 | ENCRYPTION_FLAG_128BIT = 0x00000002 132 | ENCRYPTION_FLAG_56BIT = 0x00000008 133 | FIPS_ENCRYPTION_FLAG = 0x00000010 134 | ) 135 | 136 | /** 137 | * @see http://msdn.microsoft.com/en-us/library/cc240518.aspx 138 | */ 139 | type EncryptionLevel uint32 140 | 141 | const ( 142 | ENCRYPTION_LEVEL_NONE EncryptionLevel = 0x00000000 143 | ENCRYPTION_LEVEL_LOW = 0x00000001 144 | ENCRYPTION_LEVEL_CLIENT_COMPATIBLE = 0x00000002 145 | ENCRYPTION_LEVEL_HIGH = 0x00000003 146 | ENCRYPTION_LEVEL_FIPS = 0x00000004 147 | ) 148 | 149 | /** 150 | * @see http://msdn.microsoft.com/en-us/library/cc240513.aspx 151 | */ 152 | type ChannelOptions uint32 153 | 154 | const ( 155 | CHANNEL_OPTION_INITIALIZED ChannelOptions = 0x80000000 156 | CHANNEL_OPTION_ENCRYPT_RDP = 0x40000000 157 | CHANNEL_OPTION_ENCRYPT_SC = 0x20000000 158 | CHANNEL_OPTION_ENCRYPT_CS = 0x10000000 159 | CHANNEL_OPTION_PRI_HIGH = 0x08000000 160 | CHANNEL_OPTION_PRI_MED = 0x04000000 161 | CHANNEL_OPTION_PRI_LOW = 0x02000000 162 | CHANNEL_OPTION_COMPRESS_RDP = 0x00800000 163 | CHANNEL_OPTION_COMPRESS = 0x00400000 164 | CHANNEL_OPTION_SHOW_PROTOCOL = 0x00200000 165 | REMOTE_CONTROL_PERSISTENT = 0x00100000 166 | ) 167 | 168 | /** 169 | * IBM_101_102_KEYS is the most common keyboard type 170 | */ 171 | type KeyboardType uint32 172 | 173 | const ( 174 | KT_IBM_PC_XT_83_KEY KeyboardType = 0x00000001 175 | KT_OLIVETTI = 0x00000002 176 | KT_IBM_PC_AT_84_KEY = 0x00000003 177 | KT_IBM_101_102_KEYS = 0x00000004 178 | KT_NOKIA_1050 = 0x00000005 179 | KT_NOKIA_9140 = 0x00000006 180 | KT_JAPANESE = 0x00000007 181 | ) 182 | 183 | /** 184 | * @see http://technet.microsoft.com/en-us/library/cc766503%28WS.10%29.aspx 185 | */ 186 | type KeyboardLayout uint32 187 | 188 | const ( 189 | ARABIC KeyboardLayout = 0x00000401 190 | BULGARIAN = 0x00000402 191 | CHINESE_US_KEYBOARD = 0x00000404 192 | CZECH = 0x00000405 193 | DANISH = 0x00000406 194 | GERMAN = 0x00000407 195 | GREEK = 0x00000408 196 | US = 0x00000409 197 | SPANISH = 0x0000040a 198 | FINNISH = 0x0000040b 199 | FRENCH = 0x0000040c 200 | HEBREW = 0x0000040d 201 | HUNGARIAN = 0x0000040e 202 | ICELANDIC = 0x0000040f 203 | ITALIAN = 0x00000410 204 | JAPANESE = 0x00000411 205 | KOREAN = 0x00000412 206 | DUTCH = 0x00000413 207 | NORWEGIAN = 0x00000414 208 | ) 209 | 210 | /** 211 | * @see http://msdn.microsoft.com/en-us/library/cc240521.aspx 212 | */ 213 | type CertificateType uint32 214 | 215 | const ( 216 | CERT_CHAIN_VERSION_1 CertificateType = 0x00000001 217 | CERT_CHAIN_VERSION_2 = 0x00000002 218 | ) 219 | 220 | type ChannelDef struct { 221 | Name [8]byte 222 | Options uint32 223 | } 224 | 225 | type ClientCoreData struct { 226 | RdpVersion VERSION `struc:"uint32,little"` 227 | DesktopWidth uint16 `struc:"little"` 228 | DesktopHeight uint16 `struc:"little"` 229 | ColorDepth ColorDepth `struc:"little"` 230 | SasSequence Sequence `struc:"little"` 231 | KbdLayout KeyboardLayout `struc:"little"` 232 | ClientBuild uint32 `struc:"little"` 233 | ClientName [32]byte `struc:"[32]byte"` 234 | KeyboardType uint32 `struc:"little"` 235 | KeyboardSubType uint32 `struc:"little"` 236 | KeyboardFnKeys uint32 `struc:"little"` 237 | ImeFileName [64]byte `struc:"[64]byte"` 238 | PostBeta2ColorDepth ColorDepth `struc:"little"` 239 | ClientProductId uint16 `struc:"little"` 240 | SerialNumber uint32 `struc:"little"` 241 | HighColorDepth HighColor `struc:"little"` 242 | SupportedColorDepths uint16 `struc:"little"` 243 | EarlyCapabilityFlags uint16 `struc:"little"` 244 | ClientDigProductId [64]byte `struc:"[64]byte"` 245 | ConnectionType uint8 `struc:"uint8"` 246 | Pad1octet uint8 `struc:"uint8"` 247 | ServerSelectedProtocol uint32 `struc:"little"` 248 | } 249 | 250 | func NewClientCoreData() *ClientCoreData { 251 | name, _ := os.Hostname() 252 | var ClientName [32]byte 253 | copy(ClientName[:], core.UnicodeEncode(name)[:]) 254 | return &ClientCoreData{ 255 | RDP_VERSION_5_PLUS, 1280, 800, RNS_UD_COLOR_8BPP, 256 | RNS_UD_SAS_DEL, US, 3790, ClientName, KT_IBM_101_102_KEYS, 257 | 0, 12, [64]byte{}, RNS_UD_COLOR_8BPP, 1, 0, HIGH_COLOR_24BPP, 258 | RNS_UD_15BPP_SUPPORT | RNS_UD_16BPP_SUPPORT | RNS_UD_24BPP_SUPPORT | RNS_UD_32BPP_SUPPORT, 259 | RNS_UD_CS_SUPPORT_ERRINFO_PDU, [64]byte{}, 0, 0, 0} 260 | } 261 | 262 | func (data *ClientCoreData) Block() []byte { 263 | buff := &bytes.Buffer{} 264 | core.WriteUInt16LE(CS_CORE, buff) // 01C0 265 | core.WriteUInt16LE(0xd8, buff) // d800 266 | struc.Pack(buff, data) 267 | return buff.Bytes() 268 | } 269 | 270 | type ClientNetworkData struct { 271 | ChannelCount uint32 272 | ChannelDefArray []ChannelDef 273 | } 274 | 275 | func NewClientNetworkData() *ClientNetworkData { 276 | return &ClientNetworkData{} 277 | } 278 | 279 | func (d *ClientNetworkData) Block() []byte { 280 | buff := &bytes.Buffer{} 281 | core.WriteUInt16LE(CS_NET, buff) // type 282 | core.WriteUInt16LE(0x08, buff) // len 8 283 | buff.Write([]byte{0, 0, 0, 0}) // data 284 | return buff.Bytes() 285 | } 286 | 287 | type ClientSecurityData struct { 288 | EncryptionMethods uint32 289 | ExtEncryptionMethods uint32 290 | } 291 | 292 | func NewClientSecurityData() *ClientSecurityData { 293 | return &ClientSecurityData{ 294 | ENCRYPTION_FLAG_40BIT | ENCRYPTION_FLAG_56BIT | ENCRYPTION_FLAG_128BIT, 295 | 00} 296 | } 297 | 298 | func (d *ClientSecurityData) Block() []byte { 299 | buff := &bytes.Buffer{} 300 | core.WriteUInt16LE(CS_SECURITY, buff) // type 301 | core.WriteUInt16LE(0x0c, buff) // len 12 302 | core.WriteUInt32LE(d.EncryptionMethods, buff) 303 | core.WriteUInt32LE(d.ExtEncryptionMethods, buff) 304 | return buff.Bytes() 305 | } 306 | 307 | type RSAPublicKey struct { 308 | Magic uint32 `struc:"little"` //0x31415352 309 | Keylen uint32 `struc:"little,sizeof=Modulus"` 310 | Bitlen uint32 `struc:"little"` 311 | Datalen uint32 `struc:"little"` 312 | PubExp uint32 `struc:"little"` 313 | Modulus []byte `struc:"little"` 314 | Padding []byte `struc:"[8]byte"` 315 | } 316 | 317 | type ProprietaryServerCertificate struct { 318 | DwSigAlgId uint32 `struc:"little"` //0x00000001 319 | DwKeyAlgId uint32 `struc:"little"` //0x00000001 320 | PublicKeyBlobType uint16 `struc:"little"` //0x0006 321 | PublicKeyBlobLen uint16 `struc:"little,sizeof=PublicKeyBlob"` 322 | PublicKeyBlob RSAPublicKey `struc:"little"` 323 | SignatureBlobType uint16 `struc:"little"` //0x0008 324 | SignatureBlobLen uint16 `struc:"little,sizeof=SignatureBlob"` 325 | SignatureBlob []byte `struc:"little"` 326 | //PaddingLen uint16 `struc:"little,sizeof=Padding,skip"` 327 | Padding []byte `struc:"[8]byte"` 328 | } 329 | 330 | func (p *ProprietaryServerCertificate) GetPublicKey() (uint32, []byte) { 331 | return p.PublicKeyBlob.PubExp, p.PublicKeyBlob.Modulus 332 | } 333 | func (p *ProprietaryServerCertificate) Verify() bool { 334 | //todo 335 | return true 336 | } 337 | func (p *ProprietaryServerCertificate) Encrypt() []byte { 338 | //todo 339 | return nil 340 | } 341 | func (p *ProprietaryServerCertificate) Unpack(r io.Reader) error { 342 | p.DwSigAlgId, _ = core.ReadUInt32LE(r) 343 | p.DwKeyAlgId, _ = core.ReadUInt32LE(r) 344 | p.PublicKeyBlobType, _ = core.ReadUint16LE(r) 345 | p.PublicKeyBlobLen, _ = core.ReadUint16LE(r) 346 | var b RSAPublicKey 347 | b.Magic, _ = core.ReadUInt32LE(r) 348 | b.Keylen, _ = core.ReadUInt32LE(r) 349 | b.Bitlen, _ = core.ReadUInt32LE(r) 350 | b.Datalen, _ = core.ReadUInt32LE(r) 351 | b.PubExp, _ = core.ReadUInt32LE(r) 352 | b.Modulus, _ = core.ReadBytes(int(b.Keylen)-8, r) 353 | b.Padding, _ = core.ReadBytes(8, r) 354 | p.PublicKeyBlob = b 355 | p.SignatureBlobType, _ = core.ReadUint16LE(r) 356 | p.SignatureBlobLen, _ = core.ReadUint16LE(r) 357 | p.SignatureBlob, _ = core.ReadBytes(int(p.SignatureBlobLen)-8, r) 358 | p.Padding, _ = core.ReadBytes(8, r) 359 | 360 | return nil 361 | } 362 | 363 | type CertBlob struct { 364 | CbCert uint32 `struc:"little,sizeof=AbCert"` 365 | AbCert []byte `struc:"little"` 366 | } 367 | type X509CertificateChain struct { 368 | NumCertBlobs uint32 `struc:"little,sizeof=CertBlobArray"` 369 | CertBlobArray []CertBlob `struc:"little"` 370 | Padding []byte `struc:"little"` 371 | } 372 | 373 | func (p *X509CertificateChain) GetPublicKey() (uint32, []byte) { 374 | //todo 375 | return 0, nil 376 | } 377 | func (p *X509CertificateChain) Verify() bool { 378 | return true 379 | } 380 | func (p *X509CertificateChain) Encrypt() []byte { 381 | 382 | //todo 383 | return nil 384 | } 385 | func (p *X509CertificateChain) Unpack(r io.Reader) error { 386 | return struc.Unpack(r, p) 387 | } 388 | 389 | type ServerCoreData struct { 390 | RdpVersion VERSION `struc:"uint32,little"` 391 | ClientRequestedProtocol uint32 `struc:"little"` 392 | EarlyCapabilityFlags uint32 `struc:"little"` 393 | } 394 | 395 | func NewServerCoreData() *ServerCoreData { 396 | return &ServerCoreData{ 397 | RDP_VERSION_5_PLUS, 0, 0} 398 | } 399 | 400 | func (d *ServerCoreData) Serialize() []byte { 401 | return []byte{} 402 | } 403 | 404 | func (d *ServerCoreData) ScType() Message { 405 | return SC_CORE 406 | } 407 | func (d *ServerCoreData) Unpack(r io.Reader) error { 408 | return struc.Unpack(r, d) 409 | } 410 | 411 | type ServerNetworkData struct { 412 | MCSChannelId uint16 `struc:"little"` 413 | ChannelCount uint16 `struc:"little,sizeof=ChannelIdArray"` 414 | ChannelIdArray []uint16 `struc:"little"` 415 | } 416 | 417 | func NewServerNetworkData() *ServerNetworkData { 418 | return &ServerNetworkData{} 419 | } 420 | func (d *ServerNetworkData) ScType() Message { 421 | return SC_NET 422 | } 423 | func (d *ServerNetworkData) Unpack(r io.Reader) error { 424 | return struc.Unpack(r, d) 425 | } 426 | 427 | type CertData interface { 428 | GetPublicKey() (uint32, []byte) 429 | Verify() bool 430 | Unpack(io.Reader) error 431 | } 432 | type ServerCertificate struct { 433 | DwVersion uint32 434 | CertData CertData 435 | } 436 | type ServerSecurityData struct { 437 | EncryptionMethod uint32 `struc:"little"` 438 | EncryptionLevel uint32 `struc:"little"` 439 | ServerRandomLen uint32 //0x00000020 440 | ServerCertLen uint32 441 | ServerRandom []byte 442 | ServerCertificate ServerCertificate 443 | } 444 | 445 | func NewServerSecurityData() *ServerSecurityData { 446 | return &ServerSecurityData{ 447 | 0, 0, 0x00000020, 0, []byte{}, ServerCertificate{}} 448 | } 449 | func (d *ServerSecurityData) ScType() Message { 450 | return SC_SECURITY 451 | } 452 | func (s *ServerSecurityData) Unpack(r io.Reader) error { 453 | s.EncryptionMethod, _ = core.ReadUInt32LE(r) 454 | s.EncryptionLevel, _ = core.ReadUInt32LE(r) 455 | if !(s.EncryptionMethod == 0 && s.EncryptionLevel == 0) { 456 | s.ServerRandomLen, _ = core.ReadUInt32LE(r) 457 | s.ServerCertLen, _ = core.ReadUInt32LE(r) 458 | s.ServerRandom, _ = core.ReadBytes(int(s.ServerRandomLen), r) 459 | var sc ServerCertificate 460 | data, _ := core.ReadBytes(int(s.ServerCertLen), r) 461 | rd := bytes.NewReader(data) 462 | sc.DwVersion, _ = core.ReadUInt32LE(rd) 463 | var cd CertData 464 | switch CertificateType(sc.DwVersion & 0x7fffffff) { 465 | case CERT_CHAIN_VERSION_1: 466 | glog.Debug("ProprietaryServerCertificate") 467 | cd = &ProprietaryServerCertificate{} 468 | case CERT_CHAIN_VERSION_2: 469 | glog.Debug("X509CertificateChain") 470 | cd = &X509CertificateChain{} 471 | default: 472 | glog.Error("Unsupported version:", sc.DwVersion&0x7fffffff) 473 | return errors.New("Unsupported version") 474 | } 475 | if cd != nil { 476 | //err := struc.Unpack(rd, cd) 477 | err := cd.Unpack(rd) 478 | if err != nil { 479 | glog.Error("Unpack:", err) 480 | return err 481 | } 482 | glog.Infof("d:%+v", cd) 483 | } 484 | sc.CertData = cd 485 | s.ServerCertificate = sc 486 | } 487 | 488 | return nil 489 | } 490 | 491 | func MakeConferenceCreateRequest(userData []byte) []byte { 492 | buff := &bytes.Buffer{} 493 | per.WriteChoice(0, buff) // 00 494 | per.WriteObjectIdentifier(t124_02_98_oid, buff) // 05:00:14:7c:00:01 495 | per.WriteLength(len(userData)+14, buff) 496 | per.WriteChoice(0, buff) // 00 497 | per.WriteSelection(0x08, buff) // 08 498 | per.WriteNumericString("1", 1, buff) // 00 10 499 | per.WritePadding(1, buff) // 00 500 | per.WriteNumberOfSet(1, buff) // 01 501 | per.WriteChoice(0xc0, buff) // c0 502 | per.WriteOctetStream(h221_cs_key, 4, buff) // 00 44:75:63:61 503 | per.WriteOctetStream(string(userData), 0, buff) 504 | return buff.Bytes() 505 | } 506 | 507 | type ScData interface { 508 | ScType() Message 509 | Unpack(io.Reader) error 510 | } 511 | 512 | func ReadConferenceCreateResponse(data []byte) []interface{} { 513 | ret := make([]interface{}, 0, 3) 514 | r := bytes.NewReader(data) 515 | per.ReadChoice(r) 516 | if !per.ReadObjectIdentifier(r, t124_02_98_oid) { 517 | glog.Error("NODE_RDP_PROTOCOL_T125_GCC_BAD_OBJECT_IDENTIFIER_T124") 518 | return ret 519 | } 520 | per.ReadLength(r) 521 | per.ReadChoice(r) 522 | per.ReadInteger16(r) 523 | per.ReadInteger(r) 524 | per.ReadEnumerates(r) 525 | per.ReadNumberOfSet(r) 526 | per.ReadChoice(r) 527 | 528 | if !per.ReadOctetStream(r, h221_sc_key, 4) { 529 | glog.Error("NODE_RDP_PROTOCOL_T125_GCC_BAD_H221_SC_KEY") 530 | return ret 531 | } 532 | 533 | glog.Debug("all:", SC_CORE, SC_SECURITY, SC_NET, 534 | CS_CORE, CS_SECURITY, CS_NET, CS_CLUSTER, CS_MONITOR) 535 | 536 | ln, _ := per.ReadLength(r) 537 | for ln > 0 { 538 | t, _ := core.ReadUint16LE(r) 539 | l, _ := core.ReadUint16LE(r) 540 | dataBytes, _ := core.ReadBytes(int(l)-4, r) 541 | ln = ln - l 542 | var d ScData 543 | switch Message(t) { 544 | case SC_CORE: 545 | d = &ServerCoreData{} 546 | case SC_SECURITY: 547 | d = &ServerSecurityData{} 548 | case SC_NET: 549 | d = &ServerNetworkData{} 550 | default: 551 | glog.Error("Unknown type", t) 552 | continue 553 | } 554 | r := bytes.NewReader(dataBytes) 555 | err := d.Unpack(r) 556 | if err != nil { 557 | glog.Error("Unpack:", err) 558 | if err.Error() != "EOF" { 559 | return ret 560 | } 561 | } 562 | ret = append(ret, d) 563 | glog.Debugf("d:%+v", d) 564 | } 565 | 566 | return ret 567 | } 568 | --------------------------------------------------------------------------------