Skip to content

Commit 1830bdc

Browse files
committed
Add rspec coverage for Rex::Proto::NTP
1 parent bc274b3 commit 1830bdc

File tree

3 files changed

+101
-7
lines changed

3 files changed

+101
-7
lines changed

lib/rex/proto/ntp/modes.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# -*- coding: binary -*-
2+
3+
require 'rubygems'
4+
require 'bit-struct'
5+
26
module Rex
37
module Proto
48
module NTP
@@ -25,7 +29,7 @@ class NTPGeneric < BitStruct
2529
unsigned :stratum, 8, default: 0
2630
unsigned :poll, 8, default: 0
2731
unsigned :precision, 8, default: 0
28-
char :payload, 352
32+
rest :payload
2933
end
3034

3135
# An NTP control message. Control messages are only specified for NTP
@@ -62,11 +66,12 @@ class NTPPrivate < BitStruct
6266
# 0 1 2 3
6367
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
6468
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65-
# |00 | VN | 7 |A| Sequence |
69+
# |R M| VN | 7 |A| Sequence |
6670
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6771
# | Implementation| request code |
6872
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69-
unsigned :reserved, 2, default: 0
73+
unsigned :response, 1, default: 0
74+
unsigned :more, 1, default: 0
7075
unsigned :version, 3, default: 0
7176
unsigned :mode, 3, default: 7
7277
unsigned :auth, 1, default: 0

modules/auxiliary/fuzzers/ntp/ntp_protocol_fuzzer.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ def run_host(ip)
8686
check_and_set('MODE_7_REQUEST_CODES')
8787

8888
connect_udp
89-
fuzz_version_mode(ip)
9089
fuzz_version_mode(ip, true)
90+
fuzz_version_mode(ip, false)
9191
fuzz_short(ip)
9292
fuzz_random(ip)
9393
fuzz_control(ip) if @modes.include?(6)
@@ -144,6 +144,7 @@ def fuzz_short(host)
144144
def fuzz_random(host)
145145
print_status("#{host}:#{rport} fuzzing random messages")
146146
0.upto(5) do
147+
# TODO: is there a better way to pick this size? Should more than one be tried?
147148
request = SecureRandom.random_bytes(48)
148149
what = "random #{request.size}-byte message"
149150
vprint_status("#{host}:#{rport} probing with #{what}")
@@ -154,12 +155,17 @@ def fuzz_random(host)
154155
end
155156

156157
# Sends a series of different version + mode combinations
157-
def fuzz_version_mode(host, short=false)
158+
def fuzz_version_mode(host, short)
158159
print_status("#{host}:#{rport} fuzzing #{short ? 'short ' : nil}version and mode combinations")
159160
@versions.each do |version|
160161
@modes.each do |mode|
161-
request = Rex::Proto::NTP.ntp_generic(version, mode)
162-
request = request[0, 4] if short
162+
request = Rex::Proto::NTP::NTPGeneric.new
163+
request.version = version
164+
request.mode = mode
165+
unless short
166+
# TODO: is there a better way to pick this size? Should more than one be tried?
167+
request.payload = SecureRandom.random_bytes(16)
168+
end
163169
what = "#{request.size}-byte #{short ? 'short ' : nil}version #{version} mode #{mode} message"
164170
vprint_status("#{host}:#{rport} probing with #{what}")
165171
responses = probe(host, datastore['RPORT'].to_i, request)

spec/lib/rex/proto/ntp/modes_spec.rb

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# -*- coding: binary -*-
2+
#
3+
require 'rex/proto/ntp/modes'
4+
5+
describe "Rex::Proto::NTP mode message handling" do
6+
before do
7+
@payload = 'R7' * 7
8+
end
9+
10+
describe Rex::Proto::NTP::NTPControl do
11+
before do
12+
@control_raw = "\x1e\x05\x12\x34\x12\x34\x12\x34\x00\x00\x00\x0e" + @payload
13+
@control = Rex::Proto::NTP::NTPControl.new
14+
@control.version = 3
15+
@control.response = 0
16+
@control.more = 0
17+
@control.operation = 5
18+
@control.sequence = 0x1234
19+
@control.association_id = 0x1234
20+
@control.status = 0x1234
21+
@control.payload_offset = 0
22+
@control.payload_size = 14
23+
@control.payload = @payload
24+
end
25+
26+
it 'Generates control NTP messages correctly' do
27+
@control_raw.should == @control.to_s
28+
end
29+
30+
it 'Parses private NTP messages correctly' do
31+
parsed_raw = Rex::Proto::NTP::NTPControl.new(@control_raw)
32+
@control.should == parsed_raw
33+
end
34+
end
35+
36+
describe Rex::Proto::NTP::NTPGeneric do
37+
before do
38+
@generic_raw = "\xcc\x12\x34\x56" + @payload
39+
@generic = Rex::Proto::NTP::NTPGeneric.new
40+
@generic.li = 3
41+
@generic.version = 1
42+
@generic.mode = 4
43+
@generic.stratum = 0x12
44+
@generic.poll = 0x34
45+
@generic.precision = 0x56
46+
@generic.payload = @payload
47+
end
48+
49+
it 'Generates generic NTP messages correctly' do
50+
@generic_raw.should == @generic.to_s
51+
end
52+
53+
it 'Parses private NTP messages correctly' do
54+
parsed_raw = Rex::Proto::NTP::NTPGeneric.new(@generic_raw)
55+
@generic.should == parsed_raw
56+
end
57+
end
58+
59+
describe Rex::Proto::NTP::NTPPrivate do
60+
before do
61+
@private_raw = "\x1f\x5a\x01\x99" + @payload
62+
@private = Rex::Proto::NTP::NTPPrivate.new
63+
@private.response = 0
64+
@private.more = 0
65+
@private.version = 3
66+
@private.mode = 7
67+
@private.auth = 0
68+
@private.sequence = 90
69+
@private.implementation = 1
70+
@private.request_code = 153
71+
@private.payload = @payload
72+
end
73+
74+
it 'Generates private NTP messages correctly' do
75+
@private_raw.should == @private.to_s
76+
end
77+
78+
it 'Parses private NTP messages correctly' do
79+
parsed_raw = Rex::Proto::NTP::NTPPrivate.new(@private_raw)
80+
@private.should == parsed_raw
81+
end
82+
end
83+
end

0 commit comments

Comments
 (0)