CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/spec/lib/rex/post/meterpreter/packet_spec.rb
Views: 1904
1
# -*- coding:binary -*-
2
require 'rex/post/meterpreter/packet'
3
4
RSpec.describe Rex::Post::Meterpreter::Tlv do
5
subject(:tlv) {
6
Rex::Post::Meterpreter::Tlv.new(
7
Rex::Post::Meterpreter::TLV_TYPE_STRING,
8
"test"
9
)
10
}
11
12
it "should respond to type" do
13
expect(tlv).to respond_to :type
14
end
15
16
it "should respond to value" do
17
expect(tlv).to respond_to :value
18
end
19
20
it "should respond to compress" do
21
expect(tlv).to respond_to :compress
22
end
23
24
it "should respond to inspect" do
25
expect(tlv).to respond_to :inspect
26
end
27
28
it "should respond to meta_type?" do
29
expect(tlv).to respond_to :meta_type?
30
end
31
32
it "should respond to type?" do
33
expect(tlv).to respond_to :type?
34
end
35
36
it "should respond to value?" do
37
expect(tlv).to respond_to :value?
38
end
39
40
it "should respond to to_r" do
41
expect(tlv).to respond_to :to_r
42
end
43
44
it "should respond to from_r" do
45
expect(tlv).to respond_to :from_r
46
end
47
48
context "TLV with value mapped to a single type" do
49
subject(:tlv) {
50
Rex::Post::Meterpreter::Tlv.new(
51
Rex::Post::Meterpreter::TLV_TYPE_RESULT,
52
0
53
)
54
}
55
56
it "should have a single type" do
57
expect(tlv.inspect).to eq "#<Rex::Post::Meterpreter::Tlv type=RESULT meta=INT value=0>"
58
end
59
end
60
61
context "TLV with value mapped to multiple types" do
62
subject(:tlv) {
63
Rex::Post::Meterpreter::Tlv.new(
64
151074, # Multiple TLV Types are defined as this value, as described here: https://github.com/rapid7/metasploit-framework/pull/16258#discussion_r817878469
65
0
66
)
67
}
68
69
# https://github.com/rapid7/metasploit-framework/pull/16258#discussion_r817878469
70
it "should handle multiple types in alphabetical order" do
71
expect(tlv.inspect).to eq "#<Rex::Post::Meterpreter::Tlv type=oneOf(EXT_WINDOW_ENUM_PID,PEINJECTOR_SHELLCODE_SIZE,SNIFFER_INTERFACE_ID,WEBCAM_INTERFACE_ID) meta=INT value=0>"
72
end
73
end
74
75
context "TLV with an unknown TLV type" do
76
subject(:tlv) {
77
Rex::Post::Meterpreter::Tlv.new(
78
-1,
79
0
80
)
81
}
82
83
it "should have an unknown type" do
84
expect(tlv.inspect).to eq "#<Rex::Post::Meterpreter::Tlv type=unknown--1 meta=unknown-meta-type value=\"0\">"
85
end
86
end
87
88
context "A String TLV" do
89
it "should return the correct TLV type" do
90
expect(tlv.type).to eq Rex::Post::Meterpreter::TLV_TYPE_STRING
91
end
92
93
it "should return the correct value" do
94
expect(tlv.value).to eq "test"
95
end
96
97
context "#type?" do
98
it "should return true for STRING" do
99
expect(tlv.type?(Rex::Post::Meterpreter::TLV_TYPE_STRING)).to eq true
100
end
101
102
it "should return false for UINT" do
103
expect(tlv.type?(Rex::Post::Meterpreter::TLV_TYPE_UINT)).to eq false
104
end
105
end
106
107
context "#value?" do
108
it "should return true for the correct value" do
109
expect(tlv.value?("test")).to eq true
110
end
111
112
it "should return false for an incorrect value" do
113
expect(tlv.value?("fake")).to eq false
114
end
115
end
116
117
context "#inspect" do
118
it "should return a string representation of the TLV" do
119
tlv_to_s = "#<Rex::Post::Meterpreter::Tlv type=STRING meta=STRING value=\"test\">"
120
expect(tlv.inspect).to eq tlv_to_s
121
end
122
end
123
124
context "Any non group TLV_TYPE" do
125
subject(:tlv_types){
126
excludedTypes = ["TLV_TYPE_ANY", "TLV_TYPE_EXCEPTION", "TLV_TYPE_CHANNEL_DATA_GROUP", "TLV_TYPE_TRANS_GROUP"]
127
typeList = []
128
Rex::Post::Meterpreter.constants.each do |type|
129
typeList << type.to_s if type.to_s.include?("TLV_TYPE") && !excludedTypes.include?(type.to_s)
130
end
131
typeList
132
}
133
134
it "will not raise error on inspect" do
135
tlv_types.each do |type|
136
inspectable = Rex::Post::Meterpreter::Tlv.new(
137
Rex::Post::Meterpreter.const_get(type),
138
"test"
139
)
140
expect(inspectable.inspect).to be_a_kind_of String
141
end
142
end
143
end
144
145
context "#to_r" do
146
it "should return the raw bytes of the TLV to send over the wire" do
147
tlv_bytes = "\x00\x00\x00\r\x00\x01\x00\ntest\x00"
148
expect(tlv.to_r).to eq tlv_bytes
149
end
150
end
151
152
context "#from_r" do
153
it "should adjust the tlv attributes from the given raw bytes" do
154
tlv.from_r("\x00\x00\x00\r\x00\x01\x00\ntes2\x00")
155
expect(tlv.value).to eq "tes2"
156
end
157
end
158
end
159
160
context "A Command ID TLV" do
161
context 'when the Command ID is valid' do
162
subject(:tlv) {
163
Rex::Post::Meterpreter::Tlv.new(
164
Rex::Post::Meterpreter::TLV_TYPE_COMMAND_ID,
165
1001
166
)
167
}
168
it "should have a meta type of UINT" do
169
expect(tlv.meta_type?(Rex::Post::Meterpreter::TLV_META_TYPE_UINT)).to eq true
170
end
171
172
it "should show the correct type and meta type in inspect" do
173
tlv_to_s = "#<Rex::Post::Meterpreter::Tlv type=COMMAND_ID meta=INT value=1001 command=stdapi_fs_chdir>"
174
expect(tlv.inspect).to eq tlv_to_s
175
end
176
end
177
178
context 'when the Command ID is invalid' do
179
subject(:tlv) {
180
Rex::Post::Meterpreter::Tlv.new(
181
Rex::Post::Meterpreter::TLV_TYPE_COMMAND_ID,
182
31337
183
)
184
}
185
it "should have a meta type of UINT" do
186
expect(tlv.meta_type?(Rex::Post::Meterpreter::TLV_META_TYPE_UINT)).to eq true
187
end
188
189
it "should show the correct type and meta type in inspect" do
190
tlv_to_s = "#<Rex::Post::Meterpreter::Tlv type=COMMAND_ID meta=INT value=31337 command=unknown>"
191
expect(tlv.inspect).to eq tlv_to_s
192
end
193
end
194
end
195
196
context "A String TLV with a number value" do
197
subject(:tlv) {
198
Rex::Post::Meterpreter::Tlv.new(Rex::Post::Meterpreter::TLV_TYPE_STRING,5)
199
}
200
it "should return the string version of the number" do
201
expect(tlv.value).to eq "5"
202
end
203
end
204
205
end
206
207
RSpec.describe Rex::Post::Meterpreter::GroupTlv do
208
subject(:group_tlv) {
209
Rex::Post::Meterpreter::GroupTlv.new(
210
Rex::Post::Meterpreter::TLV_TYPE_CHANNEL_DATA_GROUP
211
)
212
}
213
214
it "should respond to tlvs" do
215
expect(group_tlv).to respond_to :tlvs
216
end
217
218
it "should respond to each" do
219
expect(group_tlv).to respond_to :each
220
end
221
222
it "should respond to each_tlv" do
223
expect(group_tlv).to respond_to :each_tlv
224
end
225
226
it "should respond to each_with_index" do
227
expect(group_tlv).to respond_to :each_with_index
228
end
229
230
it "should respond to each_tlv_with_index" do
231
expect(group_tlv).to respond_to :each_tlv_with_index
232
end
233
234
it "should respond to get_tlvs" do
235
expect(group_tlv).to respond_to :get_tlvs
236
end
237
238
it "should respond to add_tlv" do
239
expect(group_tlv).to respond_to :add_tlv
240
end
241
242
it "should respond to add_tlvs" do
243
expect(group_tlv).to respond_to :add_tlvs
244
end
245
246
it "should respond to get_tlv" do
247
expect(group_tlv).to respond_to :get_tlv
248
end
249
250
it "should respond to get_tlv_value" do
251
expect(group_tlv).to respond_to :get_tlv_value
252
end
253
254
it "should respond to get_tlv_values" do
255
expect(group_tlv).to respond_to :get_tlv_values
256
end
257
258
it "should respond to has_tlv?" do
259
expect(group_tlv).to respond_to :has_tlv?
260
end
261
262
it "should respond to reset" do
263
expect(group_tlv).to respond_to :reset
264
end
265
266
it "should respond to to_r" do
267
expect(group_tlv).to respond_to :to_r
268
end
269
270
it "should respond to from_r" do
271
expect(group_tlv).to respond_to :from_r
272
end
273
274
it "should return an empty array for tlvs by default" do
275
expect(group_tlv.tlvs).to eq []
276
end
277
278
context "#add_tlv" do
279
it "should add to the tlvs array when given basic tlv parameters" do
280
group_tlv.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING,"test")
281
expect(group_tlv.tlvs.first.type).to eq Rex::Post::Meterpreter::TLV_TYPE_STRING
282
expect(group_tlv.tlvs.first.value).to eq "test"
283
end
284
285
it "should replace any existing TLV of the same type when the replace flag is set to true" do
286
group_tlv.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING,"test")
287
group_tlv.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING,"test2", true)
288
expect(group_tlv.tlvs.count).to eq 1
289
expect(group_tlv.tlvs.first.value).to eq "test2"
290
end
291
292
it "should add both if replace is set to false" do
293
group_tlv.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING,"test")
294
group_tlv.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING,"test2", false)
295
expect(group_tlv.tlvs.first.value).to eq "test"
296
expect(group_tlv.tlvs.last.value).to eq "test2"
297
end
298
end
299
300
context "#add_tlvs" do
301
it "should be able to add an array of type-value hashes" do
302
tlv_array = [
303
{'type' => Rex::Post::Meterpreter::TLV_TYPE_STRING, 'value' => "test"},
304
{'type' => Rex::Post::Meterpreter::TLV_TYPE_STRING, 'value' => "test2"}
305
]
306
group_tlv.add_tlvs(tlv_array)
307
expect(group_tlv.tlvs.count).to eq 2
308
expect(group_tlv.tlvs.first.value).to eq "test"
309
expect(group_tlv.tlvs.last.value).to eq "test2"
310
end
311
312
it "should raise an error when given something other than nil or an array" do
313
skip "RM #7598"
314
expect(group_tlv.add_tlvs("bad value")).to raise_error
315
end
316
317
it "should raise an error when given an array of objects other than hashes" do
318
skip "RM #7598"
319
expect(group_tlv.add_tlvs([1,2,3])).to raise_error
320
end
321
322
it "should raise an error when any of the hashes are missing a key" do
323
skip "RM #7598"
324
tlv_array = [
325
{:type => Rex::Post::Meterpreter::TLV_TYPE_STRING, :value => "test"},
326
{:type => Rex::Post::Meterpreter::TLV_TYPE_STRING}
327
]
328
expect(group_tlv.add_tlvs(tlv_array)).to raise_error
329
end
330
end
331
332
context "with TLVs added" do
333
before(:example) do
334
group_tlv.reset
335
tlv_array = [
336
{'type' => Rex::Post::Meterpreter::TLV_TYPE_STRING, 'value' => "test"},
337
{'type' => Rex::Post::Meterpreter::TLV_TYPE_STRING, 'value' => "test2"},
338
{'type' => Rex::Post::Meterpreter::TLV_TYPE_UINT, 'value' => 5}
339
]
340
group_tlv.add_tlvs(tlv_array)
341
@raw_group = "\x00\x00\x00/@\x00\x005\x00\x00\x00\r\x00\x01\x00\ntest\x00\x00\x00\x00\x0E\x00\x01\x00\ntest2\x00\x00\x00\x00\f\x00\x02\x00\v\x00\x00\x00\x05"
342
end
343
344
it "should empty the array of TLV when reset is called" do
345
group_tlv.reset
346
expect(group_tlv.tlvs).to eq []
347
end
348
349
it "should convert to raw bytes when to_r is called" do
350
expect(group_tlv.to_r).to eq @raw_group
351
end
352
353
354
context "#from_r" do
355
it "should build the TLV group when given the proper raw bytes" do
356
group_tlv.reset
357
group_tlv.from_r( @raw_group)
358
expect(group_tlv.tlvs[0].inspect).to eq "#<Rex::Post::Meterpreter::Tlv type=STRING meta=STRING value=\"test\">"
359
expect(group_tlv.tlvs[1].inspect).to eq "#<Rex::Post::Meterpreter::Tlv type=STRING meta=STRING value=\"test2\">"
360
expect(group_tlv.tlvs[2].inspect).to eq "#<Rex::Post::Meterpreter::Tlv type=UINT meta=INT value=5>"
361
end
362
end
363
364
365
context "#get_tlvs" do
366
it "should return all TLVs of the supplied type" do
367
tlvs = group_tlv.get_tlvs(Rex::Post::Meterpreter::TLV_TYPE_STRING)
368
expect(tlvs.count).to eq 2
369
expect(tlvs.first.value).to eq "test"
370
expect(tlvs.last.value).to eq "test2"
371
end
372
373
it "should return all TLVs when supplied the ANY TLV type" do
374
tlvs = group_tlv.get_tlvs(Rex::Post::Meterpreter::TLV_TYPE_ANY)
375
expect(tlvs.count).to eq group_tlv.tlvs.count
376
end
377
378
it "should return an empty array for a TLV type that isn't present" do
379
expect(group_tlv.get_tlvs(Rex::Post::Meterpreter::TLV_TYPE_BOOL)).to eq []
380
end
381
382
it "should return an empty array for a nonexistent TLV type" do
383
expect(group_tlv.get_tlvs(55555555)).to eq []
384
end
385
end
386
387
context "#get_tlv" do
388
it "should return the first TLV of the specified type by default" do
389
expect(group_tlv.get_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING)).to eq group_tlv.tlvs.first
390
expect(group_tlv.get_tlv(Rex::Post::Meterpreter::TLV_TYPE_UINT)).to eq group_tlv.tlvs.last
391
end
392
393
it "should return the correct TLV of the specified type for the given index" do
394
expect(group_tlv.get_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING,1)).to eq group_tlv.tlvs[1]
395
end
396
397
it "should return nil if given an out of bounds index" do
398
expect(group_tlv.get_tlv(Rex::Post::Meterpreter::TLV_TYPE_STRING,5)).to eq nil
399
end
400
401
it "should return nil if given a non-present TLV type" do
402
expect(group_tlv.get_tlv(Rex::Post::Meterpreter::TLV_TYPE_BOOL)).to eq nil
403
end
404
end
405
406
context "#get_tlv_value" do
407
it "should return the value of the first TLV with the given type" do
408
expect(group_tlv.get_tlv_value(Rex::Post::Meterpreter::TLV_TYPE_STRING)).to eq group_tlv.tlvs.first.value
409
end
410
411
it "should return the correct TLV value of the specified type for the given index" do
412
expect(group_tlv.get_tlv_value(Rex::Post::Meterpreter::TLV_TYPE_STRING,1)).to eq group_tlv.tlvs[1].value
413
end
414
415
it "should return nil if given an out of bounds index" do
416
expect(group_tlv.get_tlv_value(Rex::Post::Meterpreter::TLV_TYPE_STRING,5)).to eq nil
417
end
418
419
it "should return nil if given a non-present TLV type" do
420
expect(group_tlv.get_tlv_value(Rex::Post::Meterpreter::TLV_TYPE_BOOL)).to eq nil
421
end
422
end
423
424
context "#get_tlv_values" do
425
it "should return an array of values for the designated TLV types" do
426
expect(group_tlv.get_tlv_values(Rex::Post::Meterpreter::TLV_TYPE_STRING)).to eq ["test", "test2"]
427
end
428
429
it "should return an empty array for a non-present TLV type" do
430
expect(group_tlv.get_tlv_values(Rex::Post::Meterpreter::TLV_TYPE_BOOL)).to eq []
431
end
432
end
433
434
context "#has_tlv?" do
435
it "should return true if the TLV Type is present" do
436
expect(group_tlv.has_tlv?(Rex::Post::Meterpreter::TLV_TYPE_STRING)).to eq true
437
end
438
439
it "should return false if the TLV type is not present" do
440
expect(group_tlv.has_tlv?(Rex::Post::Meterpreter::TLV_TYPE_BOOL)).to eq false
441
end
442
end
443
end
444
end
445
446
RSpec.describe Rex::Post::Meterpreter::Packet do
447
context "Request Packet" do
448
subject(:packet) {
449
Rex::Post::Meterpreter::Packet.new(
450
Rex::Post::Meterpreter::PACKET_TYPE_REQUEST,
451
31337
452
)
453
}
454
455
it "should respond to created_at" do
456
expect(packet).to respond_to :created_at
457
end
458
459
it "should respond to response?" do
460
expect(packet).to respond_to :response?
461
end
462
463
it "should respond to method?" do
464
expect(packet).to respond_to :method?
465
end
466
467
it "should respond to method" do
468
expect(packet).to respond_to :method
469
end
470
471
it "should respond to result?" do
472
expect(packet).to respond_to :result?
473
end
474
475
it "should respond to result=" do
476
expect(packet).to respond_to :result=
477
end
478
479
it "should respond to result" do
480
expect(packet).to respond_to :result
481
end
482
483
it "should respond to rid" do
484
expect(packet).to respond_to :rid
485
end
486
487
it "should return false for response?" do
488
expect(packet.response?).to eq false
489
end
490
491
it "should evaluate the method correctly" do
492
expect(packet.method?(31337)).to eq true
493
expect(packet.method?(0xdead)).to eq false
494
end
495
496
it "should accept new methods" do
497
packet.method= 0xc0ffee
498
expect(packet.method?(0xc0ffee)).to eq true
499
end
500
501
it "should return the correct method" do
502
expect(packet.method).to eq 31337
503
end
504
505
it "should not have a result" do
506
expect(packet.result).to eq nil
507
end
508
509
it "should return a valid request id" do
510
expect(packet.rid).to match /\A\d{32}\Z/
511
end
512
513
it "should be created when Packet.create_request is called" do
514
req = Rex::Post::Meterpreter::Packet.create_request(31337)
515
expect(req.class).to eq Rex::Post::Meterpreter::Packet
516
expect(req.response?).to eq false
517
expect(req.method?(31337)).to eq true
518
end
519
520
it "should return the correct raw byte form of the packet" do
521
rid = packet.rid
522
meth = packet.method
523
raw = packet.to_r
524
packet.add_raw(raw)
525
packet.from_r
526
expect(packet.rid).to eq rid
527
expect(packet.method).to eq meth
528
end
529
end
530
531
context "a response packet" do
532
subject(:packet) {
533
Rex::Post::Meterpreter::Packet.new(
534
Rex::Post::Meterpreter::PACKET_TYPE_RESPONSE,
535
31337
536
)
537
}
538
before(:example) do
539
packet.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_RESULT, "a-ok")
540
end
541
542
it "should return the correct result" do
543
expect(packet.result).to eq "a-ok"
544
end
545
546
it "should evaluate result correctly" do
547
expect(packet.result?("a-ok")).to eq true
548
expect(packet.result?("5by5")).to eq false
549
end
550
551
it "should accept a new result" do
552
packet.result = "test2"
553
expect(packet.result).to eq "test2"
554
end
555
556
it "should be created when Packet.create_response is called" do
557
resp = Rex::Post::Meterpreter::Packet.create_response
558
expect(resp.class).to eq Rex::Post::Meterpreter::Packet
559
expect(resp.response?).to eq true
560
end
561
562
end
563
end
564
565