github.com/mholt/caddy-l4@v0.0.0-20241104153248-ec8fae209322/modules/l4rdp/matcher_test.go (about) 1 // Copyright 2024 VNXME 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package l4rdp 16 17 import ( 18 "bytes" 19 "context" 20 "errors" 21 "io" 22 "net" 23 "testing" 24 25 "github.com/caddyserver/caddy/v2" 26 "go.uber.org/zap" 27 28 "github.com/mholt/caddy-l4/layer4" 29 ) 30 31 func assertNoError(t *testing.T, err error) { 32 t.Helper() 33 if err != nil && !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) { 34 t.Fatalf("Unexpected error: %s\n", err) 35 } 36 } 37 38 func Test_MatchRDP_ProcessTPKTHeader(t *testing.T) { 39 p := [][]byte{ 40 packetValid1[0:4], packetValid2[0:4], packetValid3[0:4], packetValid4[0:4], 41 packetValid5[0:4], packetValid6[0:4], packetValid7[0:4], packetValid8[0:4], packetValid9[0:4], 42 } 43 for _, b := range p { 44 func() { 45 s := &TPKTHeader{} 46 errFrom := s.FromBytes(b) 47 assertNoError(t, errFrom) 48 sb, errTo := s.ToBytes() 49 assertNoError(t, errTo) 50 if !bytes.Equal(b, sb) { 51 t.Fatalf("test %T bytes processing: resulting bytes [% x] don't match original bytes [% x]", *s, b, sb) 52 } 53 }() 54 } 55 } 56 57 func Test_MatchRDP_ProcessX224Crq(t *testing.T) { 58 p := [][]byte{ 59 packetValid1[4:11], packetValid2[4:11], packetValid3[4:11], packetValid4[4:11], 60 packetValid5[4:11], packetValid6[4:11], packetValid7[4:11], packetValid8[4:11], packetValid9[4:11], 61 } 62 for _, b := range p { 63 func() { 64 s := &X224Crq{} 65 errFrom := s.FromBytes(b) 66 assertNoError(t, errFrom) 67 sb, errTo := s.ToBytes() 68 assertNoError(t, errTo) 69 if !bytes.Equal(b, sb) { 70 t.Fatalf("test %T bytes processing: resulting bytes [% x] don't match original bytes [% x]", *s, b, sb) 71 } 72 }() 73 } 74 } 75 76 func Test_MatchRDP_ProcessRDPCookie(t *testing.T) { 77 p := [][]byte{ 78 packetValid3[11:35], packetValid4[11:35], packetValid6[11:35], 79 } 80 for _, b := range p { 81 func() { 82 s := string(b) 83 if s != RDPCookiePrefix+"a0123"+string(ASCIIByteCR)+string(ASCIIByteLF) { 84 t.Fatalf("test RDPCookie bytes processing: resulting bytes [% x] don't match original bytes [% x]", b, []byte(s)) 85 } 86 }() 87 } 88 } 89 90 func Test_MatchRDP_ProcessRDPToken(t *testing.T) { 91 p := [][]byte{ 92 packetValid5[11:56], packetValid7[11:56], packetValid8[11:56], 93 } 94 for _, b := range p { 95 func() { 96 s := &RDPToken{} 97 errFrom := s.FromBytes(b) 98 assertNoError(t, errFrom) 99 sb, errTo := s.ToBytes() 100 assertNoError(t, errTo) 101 if !bytes.Equal(b, sb) { 102 t.Fatalf("test %T bytes processing: resulting bytes [% x] don't match original bytes [% x]", *s, b, sb) 103 } 104 }() 105 } 106 } 107 108 func Test_MatchRDP_ProcessRDPNegReq(t *testing.T) { 109 p := [][]byte{ 110 packetValid1[11:19], packetValid2[11:19], packetValid3[35:43], packetValid4[35:43], 111 packetValid5[56:64], packetValid8[56:64], 112 } 113 for _, b := range p { 114 func() { 115 s := &RDPNegReq{} 116 errFrom := s.FromBytes(b) 117 assertNoError(t, errFrom) 118 sb, errTo := s.ToBytes() 119 assertNoError(t, errTo) 120 if !bytes.Equal(b, sb) { 121 t.Fatalf("test %T bytes processing: resulting bytes [% x] don't match original bytes [% x]", *s, b, sb) 122 } 123 }() 124 } 125 } 126 127 func Test_MatchRDP_ProcessRDPCorrInfo(t *testing.T) { 128 p := [][]byte{ 129 packetValid2[19:55], packetValid3[43:79], packetValid8[64:100], 130 } 131 for _, b := range p { 132 func() { 133 s := &RDPCorrInfo{} 134 errFrom := s.FromBytes(b) 135 assertNoError(t, errFrom) 136 sb, errTo := s.ToBytes() 137 assertNoError(t, errTo) 138 if !bytes.Equal(b, sb) { 139 t.Fatalf("test %T bytes processing: resulting bytes [% x] don't match original bytes [% x]", *s, b, sb) 140 } 141 }() 142 } 143 } 144 145 func Test_MatchRDP_Match(t *testing.T) { 146 type test struct { 147 matcher *MatchRDP 148 data []byte 149 shouldMatch bool 150 } 151 152 tests := []test{ 153 // without filters 154 {matcher: &MatchRDP{}, data: packetTooShort, shouldMatch: false}, 155 {matcher: &MatchRDP{}, data: packetInvalid1, shouldMatch: false}, 156 {matcher: &MatchRDP{}, data: packetInvalid2, shouldMatch: false}, 157 {matcher: &MatchRDP{}, data: packetInvalid3, shouldMatch: false}, 158 {matcher: &MatchRDP{}, data: packetInvalid4, shouldMatch: false}, 159 {matcher: &MatchRDP{}, data: packetInvalid5, shouldMatch: false}, 160 {matcher: &MatchRDP{}, data: packetInvalid6, shouldMatch: false}, 161 {matcher: &MatchRDP{}, data: packetSemiValid1, shouldMatch: false}, 162 {matcher: &MatchRDP{}, data: packetSemiValid2, shouldMatch: false}, 163 {matcher: &MatchRDP{}, data: packetSemiValid3, shouldMatch: false}, 164 {matcher: &MatchRDP{}, data: packetSemiValid4, shouldMatch: false}, 165 {matcher: &MatchRDP{}, data: packetValid1, shouldMatch: true}, 166 {matcher: &MatchRDP{}, data: packetValid2, shouldMatch: true}, 167 {matcher: &MatchRDP{}, data: packetValid3, shouldMatch: true}, 168 {matcher: &MatchRDP{}, data: packetValid4, shouldMatch: true}, 169 {matcher: &MatchRDP{}, data: packetValid5, shouldMatch: true}, 170 {matcher: &MatchRDP{}, data: packetValid6, shouldMatch: true}, 171 {matcher: &MatchRDP{}, data: packetValid7, shouldMatch: true}, 172 {matcher: &MatchRDP{}, data: packetValid8, shouldMatch: true}, 173 {matcher: &MatchRDP{}, data: packetValid9, shouldMatch: true}, 174 {matcher: &MatchRDP{}, data: packetExtraByte, shouldMatch: false}, 175 // with filtered hash 176 {matcher: &MatchRDP{CookieHash: ""}, data: packetValid3, shouldMatch: true}, 177 {matcher: &MatchRDP{CookieHash: "a0123"}, data: packetValid3, shouldMatch: true}, 178 {matcher: &MatchRDP{CookieHash: "admin"}, data: packetValid3, shouldMatch: false}, 179 {matcher: &MatchRDP{CookieHashRegexp: ""}, data: packetValid3, shouldMatch: true}, 180 {matcher: &MatchRDP{CookieHashRegexp: "^[a-z]\\d+$"}, data: packetValid3, shouldMatch: true}, 181 {matcher: &MatchRDP{CookieHashRegexp: "^[A-Z]\\d+$"}, data: packetValid3, shouldMatch: false}, 182 // with filtered port 183 {matcher: &MatchRDP{CookiePorts: []uint16{}}, data: packetValid5, shouldMatch: true}, 184 {matcher: &MatchRDP{CookiePorts: []uint16{3389}}, data: packetValid5, shouldMatch: true}, 185 {matcher: &MatchRDP{CookiePorts: []uint16{5000}}, data: packetValid5, shouldMatch: false}, 186 // with filtered IP 187 {matcher: &MatchRDP{CookieIPs: []string{}}, data: packetValid7, shouldMatch: true}, 188 {matcher: &MatchRDP{CookieIPs: []string{"127.0.0.1/8"}}, data: packetValid7, shouldMatch: true}, 189 {matcher: &MatchRDP{CookieIPs: []string{"192.168.0.1/16"}}, data: packetValid7, shouldMatch: false}, 190 // with filtered info 191 {matcher: &MatchRDP{CustomInfo: ""}, data: packetValid9, shouldMatch: true}, 192 {matcher: &MatchRDP{CustomInfo: "anything could be here"}, data: packetValid9, shouldMatch: true}, 193 {matcher: &MatchRDP{CustomInfo: "arbitrary text"}, data: packetValid9, shouldMatch: false}, 194 {matcher: &MatchRDP{CustomInfoRegexp: ""}, data: packetValid9, shouldMatch: true}, 195 {matcher: &MatchRDP{CustomInfoRegexp: "^([A-Za-z0-9 ]+)$"}, data: packetValid9, shouldMatch: true}, 196 {matcher: &MatchRDP{CustomInfoRegexp: "^\\x00\\x01\\x02\\x03\\x04$"}, data: packetValid9, shouldMatch: false}, 197 } 198 199 ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()}) 200 defer cancel() 201 202 for i, tc := range tests { 203 func() { 204 err := tc.matcher.Provision(ctx) 205 assertNoError(t, err) 206 207 in, out := net.Pipe() 208 defer func() { 209 _, _ = io.Copy(io.Discard, out) 210 _ = out.Close() 211 }() 212 213 cx := layer4.WrapConnection(out, []byte{}, zap.NewNop()) 214 go func() { 215 _, err := in.Write(tc.data) 216 assertNoError(t, err) 217 _ = in.Close() 218 }() 219 220 matched, err := tc.matcher.Match(cx) 221 assertNoError(t, err) 222 223 if matched != tc.shouldMatch { 224 if tc.shouldMatch { 225 t.Fatalf("test %d: matcher did not match | %+v\n", i, tc.matcher) 226 } else { 227 t.Fatalf("test %d: matcher should not match | %+v\n", i, tc.matcher) 228 } 229 } 230 }() 231 } 232 } 233 234 // Packet examples 235 var packetTooShort = []byte{ 236 0x00, 0x00, 0x00, 0x00, // TPKTHeader 237 } 238 var packetInvalid1 = []byte{ 239 0x00, 0x00, 0x00, 0x00, // TPKTHeader 240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 241 } 242 var packetInvalid2 = []byte{ 243 0x03, 0x00, 0x00, 0x0B, // TPKTHeader 244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 245 } 246 var packetInvalid3 = []byte{ 247 0x03, 0x00, 0x00, 0x13, // TPKTHeader 248 0x0E, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 250 } 251 var packetInvalid4 = []byte{ 252 0x03, 0x00, 0x00, 0x37, // TPKTHeader 253 0x32, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 254 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 255 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (1/3) 256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 258 } 259 var packetInvalid5 = []byte{ 260 0x03, 0x00, 0x00, 0x4F, // TPKTHeader 261 0x4A, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 262 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, // RDPCookie (1/3) 263 // RDPCookie (2/3) 264 0x0D, 0x0A, // RDPCookie (3/3) 265 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 266 0x06, 0x00, 0x24, 0x00, // RDPCorrInfo (1/3) 267 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 269 } 270 var packetInvalid6 = []byte{ 271 0x03, 0x00, 0x00, 0x1E, // TPKTHeader 272 0x19, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPToken (1/1) 274 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 275 } 276 var packetSemiValid1 = []byte{ // we can't be sure it's RDP 277 0x03, 0x00, 0x00, 0x0B, // TPKTHeader 278 0x06, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 279 } 280 var packetSemiValid2 = []byte{ // we assume cookie hash must have at least 1 symbol 281 0x03, 0x00, 0x00, 0x4F, // TPKTHeader 282 0x4A, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 283 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, // RDPCookie (1/3) 284 // RDPCookie (2/3) 285 0x0D, 0x0A, // RDPCookie (3/3) 286 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 287 0x06, 0x00, 0x24, 0x00, // RDPCorrInfo (1/3) 288 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 290 } 291 var packetSemiValid3 = []byte{ // we assume custom info must have at least 1 symbol 292 0x03, 0x00, 0x00, 0x39, // TPKTHeader 293 0x34, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 294 // RDPCustom (1/2) 295 0x0D, 0x0A, // RDPCustom (2/2) 296 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 297 0x06, 0x00, 0x24, 0x00, // RDPCorrInfo (1/3) 298 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 300 } 301 var packetSemiValid4 = []byte{ // an empty RDPToken doesn't seem to be a valid part of RDP Connection Request 302 0x03, 0x00, 0x00, 0x1E, // TPKTHeader 303 0x19, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 304 0x03, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPToken (1/1) 305 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 306 } 307 var packetValid1 = []byte{ 308 0x03, 0x00, 0x00, 0x13, // TPKTHeader 309 0x0E, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 310 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 311 } 312 var packetValid2 = []byte{ 313 0x03, 0x00, 0x00, 0x37, // TPKTHeader 314 0x32, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 315 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 316 0x06, 0x00, 0x24, 0x00, // RDPCorrInfo (1/3) 317 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 319 } 320 var packetValid3 = []byte{ 321 0x03, 0x00, 0x00, 0x4F, // TPKTHeader 322 0x4A, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 323 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, // RDPCookie (1/3) 324 0x61, 0x30, 0x31, 0x32, 0x33, // RDPCookie (2/3) 325 0x0D, 0x0A, // RDPCookie (3/3) 326 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 327 0x06, 0x00, 0x24, 0x00, // RDPCorrInfo (1/3) 328 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 330 } 331 var packetValid4 = []byte{ 332 0x03, 0x00, 0x00, 0x2B, // TPKTHeader 333 0x26, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 334 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, // RDPCookie (1/3) 335 0x61, 0x30, 0x31, 0x32, 0x33, // RDPCookie (2/3) 336 0x0D, 0x0A, // RDPCookie (3/3) 337 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 338 } 339 var packetValid5 = []byte{ 340 0x03, 0x00, 0x00, 0x40, // TPKTHeader 341 0x3B, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 342 0x03, 0x00, 0x00, 0x2D, 0x28, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPToken (1/6) 343 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x3D, // RDPToken (2/6) 344 0x31, 0x36, 0x37, 0x37, 0x37, 0x33, 0x34, 0x33, // RDPToken (3/6) 345 0x2E, 0x31, 0x35, 0x36, 0x32, 0x39, // RDPToken (4/6) 346 0x2E, 0x30, 0x30, 0x30, 0x30, // RDPToken (5/6) 347 0x0D, 0x0A, // RDPToken (6/6) 348 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 349 } 350 var packetValid6 = []byte{ 351 0x03, 0x00, 0x00, 0x23, // TPKTHeader 352 0x1E, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 353 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x68, 0x61, 0x73, 0x68, 0x3D, // RDPCookie (1/3) 354 0x61, 0x30, 0x31, 0x32, 0x33, // RDPCookie (2/3) 355 0x0D, 0x0A, // RDPCookie (3/3) 356 } 357 var packetValid7 = []byte{ 358 0x03, 0x00, 0x00, 0x38, // TPKTHeader 359 0x33, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 360 0x03, 0x00, 0x00, 0x2D, 0x28, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPToken (1/6) 361 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x3D, // RDPToken (2/6) 362 0x31, 0x36, 0x37, 0x37, 0x37, 0x33, 0x34, 0x33, // RDPToken (3/6) 363 0x2E, 0x31, 0x35, 0x36, 0x32, 0x39, // RDPToken (4/6) 364 0x2E, 0x30, 0x30, 0x30, 0x30, // RDPToken (5/6) 365 0x0D, 0x0A, // RDPToken (6/6) 366 } 367 var packetValid8 = []byte{ 368 0x03, 0x00, 0x00, 0x64, // TPKTHeader 369 0x5F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 370 0x03, 0x00, 0x00, 0x2D, 0x28, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPToken (1/6) 371 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x3D, // RDPToken (2/6) 372 0x31, 0x36, 0x37, 0x37, 0x37, 0x33, 0x34, 0x33, // RDPToken (3/6) 373 0x2E, 0x31, 0x35, 0x36, 0x32, 0x39, // RDPToken (4/6) 374 0x2E, 0x30, 0x30, 0x30, 0x30, // RDPToken (5/6) 375 0x0D, 0x0A, // RDPToken (6/6) 376 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 377 0x06, 0x00, 0x24, 0x00, // RDPCorrInfo (1/3) 378 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 380 } 381 var packetValid9 = []byte{ 382 0x03, 0x00, 0x00, 0x23, // TPKTHeader 383 0x1E, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 384 0x61, 0x6E, 0x79, 0x74, 0x68, 0x69, 0x6E, 0x67, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64, 0x20, // RDPCustom (1/3) 385 0x62, 0x65, 0x20, 0x68, 0x65, 0x72, 0x65, // RDPCustom (2/3) 386 0x0D, 0x0A, // RDPCustom (3/3) 387 } 388 var packetExtraByte = []byte{ 389 0x03, 0x00, 0x00, 0x64, // TPKTHeader 390 0x5F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // X224Crq 391 0x03, 0x00, 0x00, 0x2D, 0x28, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPToken (1/6) 392 0x43, 0x6F, 0x6F, 0x6B, 0x69, 0x65, 0x3A, 0x20, 0x6D, 0x73, 0x74, 0x73, 0x3D, // RDPToken (2/6) 393 0x31, 0x36, 0x37, 0x37, 0x37, 0x33, 0x34, 0x33, // RDPToken (3/6) 394 0x2E, 0x31, 0x35, 0x36, 0x32, 0x39, // RDPToken (4/6) 395 0x2E, 0x30, 0x30, 0x30, 0x30, // RDPToken (5/6) 396 0x0D, 0x0A, // RDPToken (6/6) 397 0x01, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPNegReq 398 0x06, 0x00, 0x24, 0x00, // RDPCorrInfo (1/3) 399 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (2/3) 400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // RDPCorrInfo (3/3) 401 0x00, // wrong byte 402 }